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.
Files changed (77) hide show
  1. package/FrameCapture.podspec +21 -0
  2. package/LICENSE +20 -0
  3. package/README.md +158 -0
  4. package/android/build.gradle +77 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +20 -0
  7. package/android/src/main/java/com/framecapture/CaptureManager.kt +831 -0
  8. package/android/src/main/java/com/framecapture/Constants.kt +196 -0
  9. package/android/src/main/java/com/framecapture/ErrorHandler.kt +165 -0
  10. package/android/src/main/java/com/framecapture/FrameCaptureModule.kt +653 -0
  11. package/android/src/main/java/com/framecapture/FrameCapturePackage.kt +32 -0
  12. package/android/src/main/java/com/framecapture/OverlayRenderer.kt +423 -0
  13. package/android/src/main/java/com/framecapture/PermissionHandler.kt +150 -0
  14. package/android/src/main/java/com/framecapture/ScreenCaptureService.kt +366 -0
  15. package/android/src/main/java/com/framecapture/StorageManager.kt +221 -0
  16. package/android/src/main/java/com/framecapture/capture/BitmapProcessor.kt +157 -0
  17. package/android/src/main/java/com/framecapture/capture/CaptureEventEmitter.kt +120 -0
  18. package/android/src/main/java/com/framecapture/models/CaptureModels.kt +302 -0
  19. package/android/src/main/java/com/framecapture/models/EnumsAndExtensions.kt +60 -0
  20. package/android/src/main/java/com/framecapture/models/OverlayModels.kt +154 -0
  21. package/android/src/main/java/com/framecapture/service/CaptureNotificationManager.kt +286 -0
  22. package/android/src/main/java/com/framecapture/storage/StorageStrategies.kt +317 -0
  23. package/android/src/main/java/com/framecapture/utils/ValidationUtils.kt +379 -0
  24. package/app.plugin.js +1 -0
  25. package/ios/FrameCapture.h +5 -0
  26. package/ios/FrameCapture.mm +21 -0
  27. package/lib/module/NativeFrameCapture.js +24 -0
  28. package/lib/module/NativeFrameCapture.js.map +1 -0
  29. package/lib/module/api.js +146 -0
  30. package/lib/module/api.js.map +1 -0
  31. package/lib/module/constants.js +67 -0
  32. package/lib/module/constants.js.map +1 -0
  33. package/lib/module/errors.js +19 -0
  34. package/lib/module/errors.js.map +1 -0
  35. package/lib/module/events.js +58 -0
  36. package/lib/module/events.js.map +1 -0
  37. package/lib/module/index.js +24 -0
  38. package/lib/module/index.js.map +1 -0
  39. package/lib/module/normalize.js +51 -0
  40. package/lib/module/normalize.js.map +1 -0
  41. package/lib/module/package.json +1 -0
  42. package/lib/module/types.js +165 -0
  43. package/lib/module/types.js.map +1 -0
  44. package/lib/module/validation.js +190 -0
  45. package/lib/module/validation.js.map +1 -0
  46. package/lib/typescript/package.json +1 -0
  47. package/lib/typescript/plugin/src/index.d.ts +4 -0
  48. package/lib/typescript/plugin/src/index.d.ts.map +1 -0
  49. package/lib/typescript/src/NativeFrameCapture.d.ts +75 -0
  50. package/lib/typescript/src/NativeFrameCapture.d.ts.map +1 -0
  51. package/lib/typescript/src/api.d.ts +66 -0
  52. package/lib/typescript/src/api.d.ts.map +1 -0
  53. package/lib/typescript/src/constants.d.ts +41 -0
  54. package/lib/typescript/src/constants.d.ts.map +1 -0
  55. package/lib/typescript/src/errors.d.ts +14 -0
  56. package/lib/typescript/src/errors.d.ts.map +1 -0
  57. package/lib/typescript/src/events.d.ts +30 -0
  58. package/lib/typescript/src/events.d.ts.map +1 -0
  59. package/lib/typescript/src/index.d.ts +12 -0
  60. package/lib/typescript/src/index.d.ts.map +1 -0
  61. package/lib/typescript/src/normalize.d.ts +43 -0
  62. package/lib/typescript/src/normalize.d.ts.map +1 -0
  63. package/lib/typescript/src/types.d.ts +247 -0
  64. package/lib/typescript/src/types.d.ts.map +1 -0
  65. package/lib/typescript/src/validation.d.ts +15 -0
  66. package/lib/typescript/src/validation.d.ts.map +1 -0
  67. package/package.json +196 -0
  68. package/plugin/build/index.js +48 -0
  69. package/src/NativeFrameCapture.ts +86 -0
  70. package/src/api.ts +189 -0
  71. package/src/constants.ts +69 -0
  72. package/src/errors.ts +21 -0
  73. package/src/events.ts +61 -0
  74. package/src/index.tsx +31 -0
  75. package/src/normalize.ts +81 -0
  76. package/src/types.ts +327 -0
  77. package/src/validation.ts +321 -0
package/src/api.ts ADDED
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Core API functions for React Native Frame Capture
3
+ * @module api
4
+ */
5
+
6
+ import NativeFrameCapture from './NativeFrameCapture';
7
+ import { CaptureError } from './errors';
8
+ import { validateOptions, mergeOptions } from './validation';
9
+ import { normalizeOptions } from './normalize';
10
+ import {
11
+ CaptureErrorCode,
12
+ PermissionStatus,
13
+ type CaptureOptions,
14
+ type CaptureSession,
15
+ type CaptureStatus,
16
+ } from './types';
17
+
18
+ /**
19
+ * Requests MediaProjection permission from the user
20
+ *
21
+ * @returns Promise resolving to permission status
22
+ * @throws {CaptureError} if permission request fails
23
+ */
24
+ export async function requestPermission(): Promise<PermissionStatus> {
25
+ try {
26
+ const result = await NativeFrameCapture.requestPermission();
27
+ return result as PermissionStatus;
28
+ } catch (error: any) {
29
+ throw new CaptureError(
30
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
31
+ error.message || 'Failed to request permission',
32
+ error.details
33
+ );
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Checks current permission status without requesting
39
+ *
40
+ * @returns Promise resolving to current permission status
41
+ */
42
+ export async function checkPermission(): Promise<PermissionStatus> {
43
+ try {
44
+ const result = await NativeFrameCapture.checkPermission();
45
+ return result as PermissionStatus;
46
+ } catch (error: any) {
47
+ throw new CaptureError(
48
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
49
+ error.message || 'Failed to check permission',
50
+ error.details
51
+ );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Starts screen capture with the given options
57
+ *
58
+ * @param options - Capture configuration options (optional, uses defaults if not provided)
59
+ * @returns Promise resolving to capture session information
60
+ * @throws {CaptureError} if capture cannot be started
61
+ */
62
+ export async function startCapture(
63
+ options?: Partial<CaptureOptions>
64
+ ): Promise<CaptureSession> {
65
+ if (options) {
66
+ validateOptions(options);
67
+ }
68
+
69
+ const finalOptions = mergeOptions(options);
70
+ const nativeOptions = normalizeOptions(finalOptions);
71
+
72
+ try {
73
+ const result = await NativeFrameCapture.startCapture(nativeOptions);
74
+ return result as CaptureSession;
75
+ } catch (error: any) {
76
+ throw new CaptureError(
77
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
78
+ error.message || 'Failed to start capture',
79
+ error.details
80
+ );
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Stops the active capture session
86
+ *
87
+ * @returns Promise that resolves when capture is stopped
88
+ * @throws {CaptureError} if stop operation fails
89
+ */
90
+ export async function stopCapture(): Promise<void> {
91
+ try {
92
+ await NativeFrameCapture.stopCapture();
93
+ } catch (error: any) {
94
+ throw new CaptureError(
95
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
96
+ error.message || 'Failed to stop capture',
97
+ error.details
98
+ );
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Pauses the active capture session
104
+ *
105
+ * @returns Promise that resolves when capture is paused
106
+ * @throws {CaptureError} if pause operation fails
107
+ */
108
+ export async function pauseCapture(): Promise<void> {
109
+ try {
110
+ await NativeFrameCapture.pauseCapture();
111
+ } catch (error: any) {
112
+ throw new CaptureError(
113
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
114
+ error.message || 'Failed to pause capture',
115
+ error.details
116
+ );
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Resumes a paused capture session
122
+ *
123
+ * @returns Promise that resolves when capture is resumed
124
+ * @throws {CaptureError} if resume operation fails
125
+ */
126
+ export async function resumeCapture(): Promise<void> {
127
+ try {
128
+ await NativeFrameCapture.resumeCapture();
129
+ } catch (error: any) {
130
+ throw new CaptureError(
131
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
132
+ error.message || 'Failed to resume capture',
133
+ error.details
134
+ );
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Gets the current capture status
140
+ *
141
+ * @returns Promise resolving to current capture status
142
+ */
143
+ export async function getCaptureStatus(): Promise<CaptureStatus> {
144
+ try {
145
+ const result = await NativeFrameCapture.getCaptureStatus();
146
+ return result as CaptureStatus;
147
+ } catch (error: any) {
148
+ throw new CaptureError(
149
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
150
+ error.message || 'Failed to get capture status',
151
+ error.details
152
+ );
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Checks if notification permission is granted (Android 13+)
158
+ *
159
+ * @returns Promise resolving to permission status
160
+ */
161
+ export async function checkNotificationPermission(): Promise<PermissionStatus> {
162
+ try {
163
+ const result = await NativeFrameCapture.checkNotificationPermission();
164
+ return result as PermissionStatus;
165
+ } catch (error: any) {
166
+ throw new CaptureError(
167
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
168
+ error.message || 'Failed to check notification permission',
169
+ error.details
170
+ );
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Manually cleans up all temporary frame files
176
+ *
177
+ * @returns Promise that resolves when cleanup is complete
178
+ */
179
+ export async function cleanupTempFrames(): Promise<void> {
180
+ try {
181
+ await NativeFrameCapture.cleanupTempFrames();
182
+ } catch (error: any) {
183
+ throw new CaptureError(
184
+ error.code || CaptureErrorCode.SYSTEM_ERROR,
185
+ error.message || 'Failed to cleanup temp frames',
186
+ error.details
187
+ );
188
+ }
189
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Constants for React Native Frame Capture
3
+ * @module constants
4
+ */
5
+
6
+ import type {
7
+ CaptureOptions,
8
+ FileNamingConfig,
9
+ PerformanceOptions,
10
+ } from './types';
11
+
12
+ /**
13
+ * Default configuration options
14
+ */
15
+ export const DEFAULT_OPTIONS: CaptureOptions = {
16
+ capture: {
17
+ interval: 1000,
18
+ },
19
+ image: {
20
+ quality: 80,
21
+ format: 'jpeg',
22
+ },
23
+ };
24
+
25
+ /**
26
+ * Default advanced configuration (for validation fallbacks)
27
+ */
28
+ export const DEFAULT_ADVANCED_CONFIG = {
29
+ storage: {
30
+ warningThreshold: 100 * 1024 * 1024, // 100MB
31
+ },
32
+ fileNaming: {
33
+ prefix: 'capture_',
34
+ dateFormat: 'yyyyMMdd_HHmmss_SSS',
35
+ framePadding: 5,
36
+ } as Required<FileNamingConfig>,
37
+ performance: {
38
+ overlayCacheSize: 10 * 1024 * 1024, // 10MB
39
+ imageReaderBuffers: 2,
40
+ executorShutdownTimeout: 5000,
41
+ executorForcedShutdownTimeout: 1000,
42
+ } as Required<PerformanceOptions>,
43
+ };
44
+
45
+ /**
46
+ * Minimum interval between captures (milliseconds)
47
+ */
48
+ export const MIN_INTERVAL = 100;
49
+
50
+ /**
51
+ * Maximum interval between captures (milliseconds)
52
+ */
53
+ export const MAX_INTERVAL = 60000;
54
+
55
+ /**
56
+ * Minimum image quality value
57
+ */
58
+ export const MIN_QUALITY = 0;
59
+
60
+ /**
61
+ * Maximum image quality value
62
+ */
63
+ export const MAX_QUALITY = 100;
64
+
65
+ /**
66
+ * Storage warning threshold (bytes)
67
+ * @deprecated Use advanced.storage.warningThreshold in CaptureOptions instead
68
+ */
69
+ export const STORAGE_WARNING_THRESHOLD = 100 * 1024 * 1024; // 100MB
package/src/errors.ts ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Error handling for React Native Frame Capture
3
+ * @module errors
4
+ */
5
+
6
+ import { CaptureErrorCode } from './types';
7
+
8
+ /**
9
+ * Custom error class for capture operations
10
+ */
11
+ export class CaptureError extends Error {
12
+ code: CaptureErrorCode;
13
+ details?: any;
14
+
15
+ constructor(code: CaptureErrorCode, message: string, details?: any) {
16
+ super(message);
17
+ this.name = 'CaptureError';
18
+ this.code = code;
19
+ this.details = details;
20
+ }
21
+ }
package/src/events.ts ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Event handling for React Native Frame Capture
3
+ * @module events
4
+ */
5
+
6
+ import type { EventSubscription } from 'react-native';
7
+ import NativeFrameCapture from './NativeFrameCapture';
8
+ import { CaptureEventType, type CaptureEventCallback } from './types';
9
+
10
+ /**
11
+ * Adds an event listener for capture events
12
+ *
13
+ * @param event - Event type to listen for
14
+ * @param callback - Function to call when event is emitted
15
+ * @returns Subscription object that can be used to remove the listener
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const subscription = addListener(
20
+ * CaptureEventType.FRAME_CAPTURED,
21
+ * (event) => console.log('Frame captured:', event.filePath)
22
+ * );
23
+ *
24
+ * // Later, remove the listener
25
+ * subscription.remove();
26
+ * ```
27
+ */
28
+ export function addListener(
29
+ event: CaptureEventType,
30
+ callback: CaptureEventCallback
31
+ ): EventSubscription {
32
+ switch (event) {
33
+ case CaptureEventType.FRAME_CAPTURED:
34
+ return NativeFrameCapture.onFrameCaptured(callback as any);
35
+ case CaptureEventType.CAPTURE_ERROR:
36
+ return NativeFrameCapture.onCaptureError(callback as any);
37
+ case CaptureEventType.CAPTURE_STOP:
38
+ return NativeFrameCapture.onCaptureStop(callback as any);
39
+ case CaptureEventType.CAPTURE_START:
40
+ return NativeFrameCapture.onCaptureStart(callback as any);
41
+ case CaptureEventType.STORAGE_WARNING:
42
+ return NativeFrameCapture.onStorageWarning(callback as any);
43
+ case CaptureEventType.CAPTURE_PAUSE:
44
+ return NativeFrameCapture.onCapturePause(callback as any);
45
+ case CaptureEventType.CAPTURE_RESUME:
46
+ return NativeFrameCapture.onCaptureResume(callback as any);
47
+ case CaptureEventType.OVERLAY_ERROR:
48
+ return NativeFrameCapture.onOverlayError(callback as any);
49
+ default:
50
+ throw new Error(`Unknown event type: ${event}`);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * @deprecated Use subscription.remove() instead
56
+ */
57
+ export function removeAllListeners(_event: CaptureEventType): void {
58
+ console.warn(
59
+ 'removeAllListeners is deprecated in New Architecture. Use subscription.remove() instead.'
60
+ );
61
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * React Native Frame Capture
3
+ * Production-grade screen capture library for React Native Android
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+
8
+ // Export types
9
+ export * from './types';
10
+
11
+ // Export constants
12
+ export * from './constants';
13
+
14
+ // Export errors
15
+ export { CaptureError } from './errors';
16
+
17
+ // Export API functions
18
+ export {
19
+ requestPermission,
20
+ checkPermission,
21
+ startCapture,
22
+ stopCapture,
23
+ pauseCapture,
24
+ resumeCapture,
25
+ getCaptureStatus,
26
+ checkNotificationPermission,
27
+ cleanupTempFrames,
28
+ } from './api';
29
+
30
+ // Export event functions
31
+ export { addListener, removeAllListeners } from './events';
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Normalization utilities for converting organized CaptureOptions
3
+ * to the flat structure expected by native code
4
+ * @module normalize
5
+ */
6
+
7
+ import type { CaptureOptions } from './types';
8
+
9
+ /**
10
+ * Flat options structure expected by native code
11
+ */
12
+ export interface NativeCaptureOptions {
13
+ interval: number;
14
+ quality: number;
15
+ format: 'png' | 'jpeg';
16
+ saveFrames?: boolean;
17
+ storageLocation?: 'private' | 'public';
18
+ outputDirectory?: string;
19
+ scaleResolution?: number;
20
+ captureRegion?: any;
21
+ excludeStatusBar?: boolean;
22
+ notification?: any;
23
+ overlays?: any[];
24
+ advanced?: {
25
+ storage?: {
26
+ warningThreshold?: number;
27
+ };
28
+ fileNaming?: {
29
+ prefix?: string;
30
+ dateFormat?: string;
31
+ framePadding?: number;
32
+ };
33
+ performance?: {
34
+ overlayCacheSize?: number;
35
+ imageReaderBuffers?: number;
36
+ executorShutdownTimeout?: number;
37
+ executorForcedShutdownTimeout?: number;
38
+ };
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Normalizes organized CaptureOptions to flat structure for native code
44
+ */
45
+ export function normalizeOptions(
46
+ options: CaptureOptions
47
+ ): NativeCaptureOptions {
48
+ const { capture, image, storage, performance, notification, overlays } =
49
+ options;
50
+
51
+ return {
52
+ // Capture config
53
+ interval: capture.interval,
54
+
55
+ // Image config
56
+ quality: image.quality,
57
+ format: image.format,
58
+ scaleResolution: image.scaleResolution,
59
+ captureRegion: image.region,
60
+ excludeStatusBar: image.excludeStatusBar,
61
+
62
+ // Storage config
63
+ saveFrames: storage?.saveFrames,
64
+ storageLocation: storage?.location,
65
+ outputDirectory: storage?.outputDirectory,
66
+
67
+ // Pass through as-is
68
+ notification,
69
+ overlays,
70
+
71
+ // Advanced config (nested structure for native)
72
+ advanced: {
73
+ storage:
74
+ storage?.warningThreshold !== undefined
75
+ ? { warningThreshold: storage.warningThreshold }
76
+ : undefined,
77
+ fileNaming: storage?.fileNaming,
78
+ performance,
79
+ },
80
+ };
81
+ }