cuoral-ionic 0.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/LICENSE +21 -0
- package/README.md +273 -0
- package/android/src/main/AndroidManifest.xml +10 -0
- package/android/src/main/java/com/cuoral/ionic/CuoralPlugin.java +291 -0
- package/assets/icon/favicon.png +0 -0
- package/dist/bridge.d.ts +51 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +159 -0
- package/dist/cuoral.d.ts +51 -0
- package/dist/cuoral.d.ts.map +1 -0
- package/dist/cuoral.js +173 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +819 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +825 -0
- package/dist/index.js.map +1 -0
- package/dist/modal.d.ts +46 -0
- package/dist/modal.d.ts.map +1 -0
- package/dist/modal.js +220 -0
- package/dist/plugin.d.ts +76 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +134 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +24 -0
- package/dist/web.d.ts +27 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +107 -0
- package/ios/Plugin/CuoralPlugin.m +11 -0
- package/ios/Plugin/CuoralPlugin.swift +246 -0
- package/package.json +59 -0
- package/src/bridge.ts +195 -0
- package/src/cuoral.ts +208 -0
- package/src/index.ts +5 -0
- package/src/modal.ts +257 -0
- package/src/plugin.ts +190 -0
- package/src/types.ts +129 -0
- package/src/web.ts +135 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message types for communication between WebView and Native code
|
|
3
|
+
*/
|
|
4
|
+
export enum CuoralMessageType {
|
|
5
|
+
// Screen Recording
|
|
6
|
+
START_RECORDING = 'CUORAL_START_RECORDING',
|
|
7
|
+
STOP_RECORDING = 'CUORAL_STOP_RECORDING',
|
|
8
|
+
RECORDING_STARTED = 'CUORAL_RECORDING_STARTED',
|
|
9
|
+
RECORDING_STOPPED = 'CUORAL_RECORDING_STOPPED',
|
|
10
|
+
RECORDING_ERROR = 'CUORAL_RECORDING_ERROR',
|
|
11
|
+
|
|
12
|
+
// Screenshot
|
|
13
|
+
TAKE_SCREENSHOT = 'CUORAL_TAKE_SCREENSHOT',
|
|
14
|
+
SCREENSHOT_TAKEN = 'CUORAL_SCREENSHOT_TAKEN',
|
|
15
|
+
SCREENSHOT_ERROR = 'CUORAL_SCREENSHOT_ERROR',
|
|
16
|
+
|
|
17
|
+
// Widget Communication
|
|
18
|
+
WIDGET_READY = 'CUORAL_WIDGET_READY',
|
|
19
|
+
WIDGET_CLOSED = 'CUORAL_WIDGET_CLOSED',
|
|
20
|
+
|
|
21
|
+
// File Upload
|
|
22
|
+
UPLOAD_FILE = 'CUORAL_UPLOAD_FILE',
|
|
23
|
+
UPLOAD_PROGRESS = 'CUORAL_UPLOAD_PROGRESS',
|
|
24
|
+
UPLOAD_COMPLETE = 'CUORAL_UPLOAD_COMPLETE',
|
|
25
|
+
UPLOAD_ERROR = 'CUORAL_UPLOAD_ERROR',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Base message structure
|
|
30
|
+
*/
|
|
31
|
+
export interface CuoralMessage {
|
|
32
|
+
type: CuoralMessageType;
|
|
33
|
+
payload?: any;
|
|
34
|
+
timestamp?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Recording state
|
|
39
|
+
*/
|
|
40
|
+
export interface RecordingState {
|
|
41
|
+
isRecording: boolean;
|
|
42
|
+
duration?: number;
|
|
43
|
+
filePath?: string;
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Screenshot data
|
|
49
|
+
*/
|
|
50
|
+
export interface ScreenshotData {
|
|
51
|
+
base64: string;
|
|
52
|
+
mimeType: string;
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Upload progress data
|
|
59
|
+
*/
|
|
60
|
+
export interface UploadProgress {
|
|
61
|
+
loaded: number;
|
|
62
|
+
total: number;
|
|
63
|
+
percentage: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Plugin configuration
|
|
68
|
+
*/
|
|
69
|
+
export interface CuoralConfig {
|
|
70
|
+
/**
|
|
71
|
+
* Widget URL to load
|
|
72
|
+
*/
|
|
73
|
+
widgetUrl: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Enable debug logging
|
|
77
|
+
*/
|
|
78
|
+
debug?: boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Custom message handler
|
|
82
|
+
*/
|
|
83
|
+
onMessage?: (message: CuoralMessage) => void;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Recording quality (0.0 - 1.0)
|
|
87
|
+
*/
|
|
88
|
+
recordingQuality?: number;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Screenshot quality (0.0 - 1.0)
|
|
92
|
+
*/
|
|
93
|
+
screenshotQuality?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Recording options
|
|
98
|
+
*/
|
|
99
|
+
export interface RecordingOptions {
|
|
100
|
+
/**
|
|
101
|
+
* Video quality (0.0 - 1.0)
|
|
102
|
+
*/
|
|
103
|
+
quality?: number;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Include audio
|
|
107
|
+
*/
|
|
108
|
+
includeAudio?: boolean;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Maximum duration in seconds
|
|
112
|
+
*/
|
|
113
|
+
maxDuration?: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Screenshot options
|
|
118
|
+
*/
|
|
119
|
+
export interface ScreenshotOptions {
|
|
120
|
+
/**
|
|
121
|
+
* Image quality (0.0 - 1.0)
|
|
122
|
+
*/
|
|
123
|
+
quality?: number;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Image format
|
|
127
|
+
*/
|
|
128
|
+
format?: 'png' | 'jpeg';
|
|
129
|
+
}
|
package/src/web.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import { CuoralPluginInterface } from './plugin';
|
|
3
|
+
import {
|
|
4
|
+
RecordingOptions,
|
|
5
|
+
RecordingState,
|
|
6
|
+
ScreenshotOptions,
|
|
7
|
+
ScreenshotData,
|
|
8
|
+
} from './types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Web implementation (for testing in browser)
|
|
12
|
+
*/
|
|
13
|
+
export class CuoralPluginWeb extends WebPlugin implements CuoralPluginInterface {
|
|
14
|
+
private isRecording = false;
|
|
15
|
+
private recordingStartTime?: number;
|
|
16
|
+
|
|
17
|
+
async startRecording(options?: RecordingOptions): Promise<{ success: boolean }> {
|
|
18
|
+
console.log('[Cuoral Web] Start recording', options);
|
|
19
|
+
|
|
20
|
+
// Check if Screen Capture API is available
|
|
21
|
+
if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
|
|
22
|
+
throw new Error('Screen recording is not supported in this browser');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Request screen capture
|
|
27
|
+
const stream = await navigator.mediaDevices.getDisplayMedia({
|
|
28
|
+
video: true,
|
|
29
|
+
audio: options?.includeAudio || false,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.isRecording = true;
|
|
33
|
+
this.recordingStartTime = Date.now();
|
|
34
|
+
|
|
35
|
+
// Store stream for later stopping
|
|
36
|
+
(window as any).__cuoralRecordingStream = stream;
|
|
37
|
+
|
|
38
|
+
return { success: true };
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('[Cuoral Web] Failed to start recording:', error);
|
|
41
|
+
return { success: false };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async stopRecording(): Promise<{ success: boolean; filePath?: string; duration?: number }> {
|
|
46
|
+
console.log('[Cuoral Web] Stop recording');
|
|
47
|
+
|
|
48
|
+
if (!this.isRecording) {
|
|
49
|
+
return { success: false };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const stream = (window as any).__cuoralRecordingStream as MediaStream;
|
|
53
|
+
if (stream) {
|
|
54
|
+
stream.getTracks().forEach(track => track.stop());
|
|
55
|
+
delete (window as any).__cuoralRecordingStream;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const duration = this.recordingStartTime
|
|
59
|
+
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
60
|
+
: 0;
|
|
61
|
+
|
|
62
|
+
this.isRecording = false;
|
|
63
|
+
this.recordingStartTime = undefined;
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
duration,
|
|
68
|
+
filePath: 'web-recording-not-saved',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async getRecordingState(): Promise<RecordingState> {
|
|
73
|
+
return {
|
|
74
|
+
isRecording: this.isRecording,
|
|
75
|
+
duration: this.recordingStartTime
|
|
76
|
+
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
77
|
+
: undefined,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async takeScreenshot(options?: ScreenshotOptions): Promise<ScreenshotData> {
|
|
82
|
+
console.log('[Cuoral Web] Take screenshot', options);
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
// Use Screen Capture API
|
|
86
|
+
const stream = await navigator.mediaDevices.getDisplayMedia({
|
|
87
|
+
video: { width: 1920, height: 1080 },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Capture frame from video stream
|
|
91
|
+
const video = document.createElement('video');
|
|
92
|
+
video.srcObject = stream;
|
|
93
|
+
video.play();
|
|
94
|
+
|
|
95
|
+
await new Promise(resolve => {
|
|
96
|
+
video.onloadedmetadata = resolve;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const canvas = document.createElement('canvas');
|
|
100
|
+
canvas.width = video.videoWidth;
|
|
101
|
+
canvas.height = video.videoHeight;
|
|
102
|
+
|
|
103
|
+
const ctx = canvas.getContext('2d');
|
|
104
|
+
ctx?.drawImage(video, 0, 0);
|
|
105
|
+
|
|
106
|
+
// Stop stream
|
|
107
|
+
stream.getTracks().forEach(track => track.stop());
|
|
108
|
+
|
|
109
|
+
// Convert to base64
|
|
110
|
+
const format = options?.format || 'png';
|
|
111
|
+
const quality = options?.quality || 0.92;
|
|
112
|
+
const base64 = canvas.toDataURL(`image/${format}`, quality);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
base64: base64.split(',')[1],
|
|
116
|
+
mimeType: `image/${format}`,
|
|
117
|
+
width: canvas.width,
|
|
118
|
+
height: canvas.height,
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('[Cuoral Web] Failed to take screenshot:', error);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async isRecordingSupported(): Promise<{ supported: boolean }> {
|
|
127
|
+
const supported = !!(navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia);
|
|
128
|
+
return { supported };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async requestPermissions(): Promise<{ granted: boolean }> {
|
|
132
|
+
// Web doesn't require explicit permissions - they're requested on demand
|
|
133
|
+
return { granted: true };
|
|
134
|
+
}
|
|
135
|
+
}
|