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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/modal.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cuoral Modal Manager
|
|
3
|
+
* Handles full-screen modal display with floating button
|
|
4
|
+
*/
|
|
5
|
+
export declare class CuoralModal {
|
|
6
|
+
private modalElement?;
|
|
7
|
+
private iframeElement?;
|
|
8
|
+
private floatingButton?;
|
|
9
|
+
private isOpen;
|
|
10
|
+
private widgetUrl;
|
|
11
|
+
private showFloatingButton;
|
|
12
|
+
constructor(widgetUrl: string, showFloatingButton?: boolean);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the modal and floating button
|
|
15
|
+
*/
|
|
16
|
+
initialize(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Create floating chat button
|
|
19
|
+
*/
|
|
20
|
+
private createFloatingButton;
|
|
21
|
+
/**
|
|
22
|
+
* Create modal structure
|
|
23
|
+
*/
|
|
24
|
+
private createModal;
|
|
25
|
+
/**
|
|
26
|
+
* Open the modal
|
|
27
|
+
*/
|
|
28
|
+
open(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Close the modal
|
|
31
|
+
*/
|
|
32
|
+
close(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Check if modal is open
|
|
35
|
+
*/
|
|
36
|
+
isModalOpen(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Destroy modal and floating button
|
|
39
|
+
*/
|
|
40
|
+
destroy(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get iframe element for communication
|
|
43
|
+
*/
|
|
44
|
+
getIframe(): HTMLIFrameElement | undefined;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../src/modal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAU;gBAExB,SAAS,EAAE,MAAM,EAAE,kBAAkB,UAAO;IAKxD;;OAEG;IACI,UAAU,IAAI,IAAI;IAOzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkD5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAkGnB;;OAEG;IACI,IAAI,IAAI,IAAI;IAsBnB;;OAEG;IACI,KAAK,IAAI,IAAI;IAqBpB;;OAEG;IACI,WAAW,IAAI,OAAO;IAI7B;;OAEG;IACI,OAAO,IAAI,IAAI;IAUtB;;OAEG;IACI,SAAS,IAAI,iBAAiB,GAAG,SAAS;CAGlD"}
|
package/dist/modal.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cuoral Modal Manager
|
|
3
|
+
* Handles full-screen modal display with floating button
|
|
4
|
+
*/
|
|
5
|
+
export class CuoralModal {
|
|
6
|
+
constructor(widgetUrl, showFloatingButton = true) {
|
|
7
|
+
this.isOpen = false;
|
|
8
|
+
this.widgetUrl = widgetUrl;
|
|
9
|
+
this.showFloatingButton = showFloatingButton;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Initialize the modal and floating button
|
|
13
|
+
*/
|
|
14
|
+
initialize() {
|
|
15
|
+
if (this.showFloatingButton) {
|
|
16
|
+
this.createFloatingButton();
|
|
17
|
+
}
|
|
18
|
+
this.createModal();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create floating chat button
|
|
22
|
+
*/
|
|
23
|
+
createFloatingButton() {
|
|
24
|
+
this.floatingButton = document.createElement('div');
|
|
25
|
+
this.floatingButton.id = 'cuoral-floating-button';
|
|
26
|
+
this.floatingButton.innerHTML = `
|
|
27
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
28
|
+
<path d="M20 2H4C2.9 2 2 2.9 2 4V22L6 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2ZM20 16H6L4 18V4H20V16Z" fill="white"/>
|
|
29
|
+
</svg>
|
|
30
|
+
`;
|
|
31
|
+
// Styles
|
|
32
|
+
Object.assign(this.floatingButton.style, {
|
|
33
|
+
position: 'fixed',
|
|
34
|
+
bottom: '20px',
|
|
35
|
+
right: '20px',
|
|
36
|
+
width: '56px',
|
|
37
|
+
height: '56px',
|
|
38
|
+
borderRadius: '50%',
|
|
39
|
+
backgroundColor: '#007AFF',
|
|
40
|
+
display: 'flex',
|
|
41
|
+
alignItems: 'center',
|
|
42
|
+
justifyContent: 'center',
|
|
43
|
+
cursor: 'pointer',
|
|
44
|
+
boxShadow: '0 4px 12px rgba(0, 122, 255, 0.4)',
|
|
45
|
+
zIndex: '999999',
|
|
46
|
+
transition: 'transform 0.2s, box-shadow 0.2s'
|
|
47
|
+
});
|
|
48
|
+
// Hover effect
|
|
49
|
+
this.floatingButton.addEventListener('mouseenter', () => {
|
|
50
|
+
if (this.floatingButton) {
|
|
51
|
+
this.floatingButton.style.transform = 'scale(1.1)';
|
|
52
|
+
this.floatingButton.style.boxShadow = '0 6px 16px rgba(0, 122, 255, 0.5)';
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
this.floatingButton.addEventListener('mouseleave', () => {
|
|
56
|
+
if (this.floatingButton) {
|
|
57
|
+
this.floatingButton.style.transform = 'scale(1)';
|
|
58
|
+
this.floatingButton.style.boxShadow = '0 4px 12px rgba(0, 122, 255, 0.4)';
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Click to open modal
|
|
62
|
+
this.floatingButton.addEventListener('click', () => {
|
|
63
|
+
this.open();
|
|
64
|
+
});
|
|
65
|
+
document.body.appendChild(this.floatingButton);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create modal structure
|
|
69
|
+
*/
|
|
70
|
+
createModal() {
|
|
71
|
+
// Modal container
|
|
72
|
+
this.modalElement = document.createElement('div');
|
|
73
|
+
this.modalElement.id = 'cuoral-modal';
|
|
74
|
+
Object.assign(this.modalElement.style, {
|
|
75
|
+
position: 'fixed',
|
|
76
|
+
top: '0',
|
|
77
|
+
left: '0',
|
|
78
|
+
width: '100%',
|
|
79
|
+
height: '100%',
|
|
80
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
81
|
+
display: 'none',
|
|
82
|
+
alignItems: 'center',
|
|
83
|
+
justifyContent: 'center',
|
|
84
|
+
zIndex: '1000000',
|
|
85
|
+
opacity: '0',
|
|
86
|
+
transition: 'opacity 0.3s ease',
|
|
87
|
+
padding: '60px 0'
|
|
88
|
+
});
|
|
89
|
+
// Modal content (with margin)
|
|
90
|
+
const modalContent = document.createElement('div');
|
|
91
|
+
Object.assign(modalContent.style, {
|
|
92
|
+
width: '100%',
|
|
93
|
+
height: '100%',
|
|
94
|
+
maxWidth: '100%',
|
|
95
|
+
maxHeight: '100%',
|
|
96
|
+
position: 'relative',
|
|
97
|
+
backgroundColor: 'transparent',
|
|
98
|
+
display: 'flex',
|
|
99
|
+
flexDirection: 'column',
|
|
100
|
+
borderRadius: '12px',
|
|
101
|
+
overflow: 'hidden'
|
|
102
|
+
});
|
|
103
|
+
// Close button
|
|
104
|
+
const closeButton = document.createElement('div');
|
|
105
|
+
closeButton.innerHTML = `
|
|
106
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
107
|
+
<path d="M18 6L6 18M6 6L18 18" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
108
|
+
</svg>
|
|
109
|
+
`;
|
|
110
|
+
Object.assign(closeButton.style, {
|
|
111
|
+
position: 'absolute',
|
|
112
|
+
top: '20px',
|
|
113
|
+
right: '20px',
|
|
114
|
+
width: '40px',
|
|
115
|
+
height: '40px',
|
|
116
|
+
borderRadius: '50%',
|
|
117
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
118
|
+
display: 'flex',
|
|
119
|
+
alignItems: 'center',
|
|
120
|
+
justifyContent: 'center',
|
|
121
|
+
cursor: 'pointer',
|
|
122
|
+
zIndex: '1000001',
|
|
123
|
+
transition: 'background-color 0.2s'
|
|
124
|
+
});
|
|
125
|
+
closeButton.addEventListener('mouseenter', () => {
|
|
126
|
+
closeButton.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
|
|
127
|
+
});
|
|
128
|
+
closeButton.addEventListener('mouseleave', () => {
|
|
129
|
+
closeButton.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
|
|
130
|
+
});
|
|
131
|
+
closeButton.addEventListener('click', () => {
|
|
132
|
+
this.close();
|
|
133
|
+
});
|
|
134
|
+
// Iframe
|
|
135
|
+
this.iframeElement = document.createElement('iframe');
|
|
136
|
+
this.iframeElement.id = 'cuoral-widget-iframe';
|
|
137
|
+
this.iframeElement.src = this.widgetUrl;
|
|
138
|
+
Object.assign(this.iframeElement.style, {
|
|
139
|
+
width: '100%',
|
|
140
|
+
height: '100%',
|
|
141
|
+
border: 'none',
|
|
142
|
+
backgroundColor: 'white'
|
|
143
|
+
});
|
|
144
|
+
modalContent.appendChild(closeButton);
|
|
145
|
+
modalContent.appendChild(this.iframeElement);
|
|
146
|
+
this.modalElement.appendChild(modalContent);
|
|
147
|
+
// Close on backdrop click
|
|
148
|
+
this.modalElement.addEventListener('click', (e) => {
|
|
149
|
+
if (e.target === this.modalElement) {
|
|
150
|
+
this.close();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
document.body.appendChild(this.modalElement);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Open the modal
|
|
157
|
+
*/
|
|
158
|
+
open() {
|
|
159
|
+
if (this.isOpen || !this.modalElement)
|
|
160
|
+
return;
|
|
161
|
+
this.isOpen = true;
|
|
162
|
+
this.modalElement.style.display = 'flex';
|
|
163
|
+
// Trigger animation
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
if (this.modalElement) {
|
|
166
|
+
this.modalElement.style.opacity = '1';
|
|
167
|
+
}
|
|
168
|
+
}, 10);
|
|
169
|
+
// Hide floating button when modal is open
|
|
170
|
+
if (this.floatingButton) {
|
|
171
|
+
this.floatingButton.style.display = 'none';
|
|
172
|
+
}
|
|
173
|
+
// Prevent body scroll
|
|
174
|
+
document.body.style.overflow = 'hidden';
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Close the modal
|
|
178
|
+
*/
|
|
179
|
+
close() {
|
|
180
|
+
if (!this.isOpen || !this.modalElement)
|
|
181
|
+
return;
|
|
182
|
+
this.isOpen = false;
|
|
183
|
+
this.modalElement.style.opacity = '0';
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
if (this.modalElement) {
|
|
186
|
+
this.modalElement.style.display = 'none';
|
|
187
|
+
}
|
|
188
|
+
// Show floating button again
|
|
189
|
+
if (this.floatingButton) {
|
|
190
|
+
this.floatingButton.style.display = 'flex';
|
|
191
|
+
}
|
|
192
|
+
// Restore body scroll
|
|
193
|
+
document.body.style.overflow = '';
|
|
194
|
+
}, 300);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Check if modal is open
|
|
198
|
+
*/
|
|
199
|
+
isModalOpen() {
|
|
200
|
+
return this.isOpen;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Destroy modal and floating button
|
|
204
|
+
*/
|
|
205
|
+
destroy() {
|
|
206
|
+
if (this.modalElement) {
|
|
207
|
+
this.modalElement.remove();
|
|
208
|
+
}
|
|
209
|
+
if (this.floatingButton) {
|
|
210
|
+
this.floatingButton.remove();
|
|
211
|
+
}
|
|
212
|
+
document.body.style.overflow = '';
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get iframe element for communication
|
|
216
|
+
*/
|
|
217
|
+
getIframe() {
|
|
218
|
+
return this.iframeElement;
|
|
219
|
+
}
|
|
220
|
+
}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { RecordingOptions, RecordingState, ScreenshotOptions, ScreenshotData } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Capacitor Plugin Interface
|
|
4
|
+
*/
|
|
5
|
+
export interface CuoralPluginInterface {
|
|
6
|
+
/**
|
|
7
|
+
* Start screen recording
|
|
8
|
+
*/
|
|
9
|
+
startRecording(options?: RecordingOptions): Promise<{
|
|
10
|
+
success: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Stop screen recording
|
|
14
|
+
*/
|
|
15
|
+
stopRecording(): Promise<{
|
|
16
|
+
success: boolean;
|
|
17
|
+
filePath?: string;
|
|
18
|
+
duration?: number;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Get recording state
|
|
22
|
+
*/
|
|
23
|
+
getRecordingState(): Promise<RecordingState>;
|
|
24
|
+
/**
|
|
25
|
+
* Take screenshot
|
|
26
|
+
*/
|
|
27
|
+
takeScreenshot(options?: ScreenshotOptions): Promise<ScreenshotData>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if recording is supported
|
|
30
|
+
*/
|
|
31
|
+
isRecordingSupported(): Promise<{
|
|
32
|
+
supported: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Request recording permissions
|
|
36
|
+
*/
|
|
37
|
+
requestPermissions(): Promise<{
|
|
38
|
+
granted: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Register the Capacitor plugin
|
|
43
|
+
*/
|
|
44
|
+
declare const CuoralPlugin: CuoralPluginInterface;
|
|
45
|
+
export { CuoralPlugin };
|
|
46
|
+
/**
|
|
47
|
+
* High-level API for easier integration
|
|
48
|
+
*/
|
|
49
|
+
export declare class CuoralRecorder {
|
|
50
|
+
private isRecording;
|
|
51
|
+
private recordingStartTime?;
|
|
52
|
+
/**
|
|
53
|
+
* Start recording with automatic permission handling
|
|
54
|
+
*/
|
|
55
|
+
startRecording(options?: RecordingOptions): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Stop recording
|
|
58
|
+
*/
|
|
59
|
+
stopRecording(): Promise<{
|
|
60
|
+
filePath?: string;
|
|
61
|
+
duration?: number;
|
|
62
|
+
} | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Take screenshot
|
|
65
|
+
*/
|
|
66
|
+
takeScreenshot(options?: ScreenshotOptions): Promise<ScreenshotData | null>;
|
|
67
|
+
/**
|
|
68
|
+
* Get current recording state
|
|
69
|
+
*/
|
|
70
|
+
getState(): Promise<RecordingState>;
|
|
71
|
+
/**
|
|
72
|
+
* Post message to WebView
|
|
73
|
+
*/
|
|
74
|
+
private postMessage;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1E;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAErF;;OAEG;IACH,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAE7C;;OAEG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAErE;;OAEG;IACH,oBAAoB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAExD;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;GAEG;AACH,QAAA,MAAM,YAAY,uBAEhB,CAAC;AAEH,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAEpC;;OAEG;IACG,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4ClE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAwC/E;;OAEG;IACG,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqBjF;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAIzC;;OAEG;IACH,OAAO,CAAC,WAAW;CAKpB"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
import { CuoralMessageType, } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Register the Capacitor plugin
|
|
5
|
+
*/
|
|
6
|
+
const CuoralPlugin = registerPlugin('CuoralPlugin', {
|
|
7
|
+
web: () => import('./web').then(m => new m.CuoralPluginWeb()),
|
|
8
|
+
});
|
|
9
|
+
export { CuoralPlugin };
|
|
10
|
+
/**
|
|
11
|
+
* High-level API for easier integration
|
|
12
|
+
*/
|
|
13
|
+
export class CuoralRecorder {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.isRecording = false;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Start recording with automatic permission handling
|
|
19
|
+
*/
|
|
20
|
+
async startRecording(options) {
|
|
21
|
+
try {
|
|
22
|
+
// Check if already recording
|
|
23
|
+
if (this.isRecording) {
|
|
24
|
+
console.warn('[Cuoral] Already recording');
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// Check support
|
|
28
|
+
const { supported } = await CuoralPlugin.isRecordingSupported();
|
|
29
|
+
if (!supported) {
|
|
30
|
+
throw new Error('Screen recording is not supported on this device');
|
|
31
|
+
}
|
|
32
|
+
// Request permissions
|
|
33
|
+
const { granted } = await CuoralPlugin.requestPermissions();
|
|
34
|
+
if (!granted) {
|
|
35
|
+
throw new Error('Recording permissions not granted');
|
|
36
|
+
}
|
|
37
|
+
// Start recording
|
|
38
|
+
const result = await CuoralPlugin.startRecording(options);
|
|
39
|
+
if (result.success) {
|
|
40
|
+
this.isRecording = true;
|
|
41
|
+
this.recordingStartTime = Date.now();
|
|
42
|
+
// Post message to widget
|
|
43
|
+
this.postMessage({
|
|
44
|
+
type: CuoralMessageType.RECORDING_STARTED,
|
|
45
|
+
payload: { timestamp: this.recordingStartTime },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return result.success;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.error('[Cuoral] Failed to start recording:', error);
|
|
52
|
+
this.postMessage({
|
|
53
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
54
|
+
payload: { error: error.message },
|
|
55
|
+
});
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Stop recording
|
|
61
|
+
*/
|
|
62
|
+
async stopRecording() {
|
|
63
|
+
try {
|
|
64
|
+
if (!this.isRecording) {
|
|
65
|
+
console.warn('[Cuoral] Not recording');
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const result = await CuoralPlugin.stopRecording();
|
|
69
|
+
if (result.success) {
|
|
70
|
+
this.isRecording = false;
|
|
71
|
+
const duration = this.recordingStartTime
|
|
72
|
+
? Math.floor((Date.now() - this.recordingStartTime) / 1000)
|
|
73
|
+
: 0;
|
|
74
|
+
// Post message to widget
|
|
75
|
+
this.postMessage({
|
|
76
|
+
type: CuoralMessageType.RECORDING_STOPPED,
|
|
77
|
+
payload: {
|
|
78
|
+
filePath: result.filePath,
|
|
79
|
+
duration: result.duration || duration,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
filePath: result.filePath,
|
|
84
|
+
duration: result.duration || duration,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('[Cuoral] Failed to stop recording:', error);
|
|
91
|
+
this.postMessage({
|
|
92
|
+
type: CuoralMessageType.RECORDING_ERROR,
|
|
93
|
+
payload: { error: error.message },
|
|
94
|
+
});
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Take screenshot
|
|
100
|
+
*/
|
|
101
|
+
async takeScreenshot(options) {
|
|
102
|
+
try {
|
|
103
|
+
const screenshot = await CuoralPlugin.takeScreenshot(options);
|
|
104
|
+
// Post message to widget
|
|
105
|
+
this.postMessage({
|
|
106
|
+
type: CuoralMessageType.SCREENSHOT_TAKEN,
|
|
107
|
+
payload: screenshot,
|
|
108
|
+
});
|
|
109
|
+
return screenshot;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
console.error('[Cuoral] Failed to take screenshot:', error);
|
|
113
|
+
this.postMessage({
|
|
114
|
+
type: CuoralMessageType.SCREENSHOT_ERROR,
|
|
115
|
+
payload: { error: error.message },
|
|
116
|
+
});
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get current recording state
|
|
122
|
+
*/
|
|
123
|
+
async getState() {
|
|
124
|
+
return await CuoralPlugin.getRecordingState();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Post message to WebView
|
|
128
|
+
*/
|
|
129
|
+
postMessage(message) {
|
|
130
|
+
if (typeof window !== 'undefined' && window.postMessage) {
|
|
131
|
+
window.postMessage(message, '*');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message types for communication between WebView and Native code
|
|
3
|
+
*/
|
|
4
|
+
export declare enum CuoralMessageType {
|
|
5
|
+
START_RECORDING = "CUORAL_START_RECORDING",
|
|
6
|
+
STOP_RECORDING = "CUORAL_STOP_RECORDING",
|
|
7
|
+
RECORDING_STARTED = "CUORAL_RECORDING_STARTED",
|
|
8
|
+
RECORDING_STOPPED = "CUORAL_RECORDING_STOPPED",
|
|
9
|
+
RECORDING_ERROR = "CUORAL_RECORDING_ERROR",
|
|
10
|
+
TAKE_SCREENSHOT = "CUORAL_TAKE_SCREENSHOT",
|
|
11
|
+
SCREENSHOT_TAKEN = "CUORAL_SCREENSHOT_TAKEN",
|
|
12
|
+
SCREENSHOT_ERROR = "CUORAL_SCREENSHOT_ERROR",
|
|
13
|
+
WIDGET_READY = "CUORAL_WIDGET_READY",
|
|
14
|
+
WIDGET_CLOSED = "CUORAL_WIDGET_CLOSED",
|
|
15
|
+
UPLOAD_FILE = "CUORAL_UPLOAD_FILE",
|
|
16
|
+
UPLOAD_PROGRESS = "CUORAL_UPLOAD_PROGRESS",
|
|
17
|
+
UPLOAD_COMPLETE = "CUORAL_UPLOAD_COMPLETE",
|
|
18
|
+
UPLOAD_ERROR = "CUORAL_UPLOAD_ERROR"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Base message structure
|
|
22
|
+
*/
|
|
23
|
+
export interface CuoralMessage {
|
|
24
|
+
type: CuoralMessageType;
|
|
25
|
+
payload?: any;
|
|
26
|
+
timestamp?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Recording state
|
|
30
|
+
*/
|
|
31
|
+
export interface RecordingState {
|
|
32
|
+
isRecording: boolean;
|
|
33
|
+
duration?: number;
|
|
34
|
+
filePath?: string;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Screenshot data
|
|
39
|
+
*/
|
|
40
|
+
export interface ScreenshotData {
|
|
41
|
+
base64: string;
|
|
42
|
+
mimeType: string;
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Upload progress data
|
|
48
|
+
*/
|
|
49
|
+
export interface UploadProgress {
|
|
50
|
+
loaded: number;
|
|
51
|
+
total: number;
|
|
52
|
+
percentage: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Plugin configuration
|
|
56
|
+
*/
|
|
57
|
+
export interface CuoralConfig {
|
|
58
|
+
/**
|
|
59
|
+
* Widget URL to load
|
|
60
|
+
*/
|
|
61
|
+
widgetUrl: string;
|
|
62
|
+
/**
|
|
63
|
+
* Enable debug logging
|
|
64
|
+
*/
|
|
65
|
+
debug?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Custom message handler
|
|
68
|
+
*/
|
|
69
|
+
onMessage?: (message: CuoralMessage) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Recording quality (0.0 - 1.0)
|
|
72
|
+
*/
|
|
73
|
+
recordingQuality?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Screenshot quality (0.0 - 1.0)
|
|
76
|
+
*/
|
|
77
|
+
screenshotQuality?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Recording options
|
|
81
|
+
*/
|
|
82
|
+
export interface RecordingOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Video quality (0.0 - 1.0)
|
|
85
|
+
*/
|
|
86
|
+
quality?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Include audio
|
|
89
|
+
*/
|
|
90
|
+
includeAudio?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Maximum duration in seconds
|
|
93
|
+
*/
|
|
94
|
+
maxDuration?: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Screenshot options
|
|
98
|
+
*/
|
|
99
|
+
export interface ScreenshotOptions {
|
|
100
|
+
/**
|
|
101
|
+
* Image quality (0.0 - 1.0)
|
|
102
|
+
*/
|
|
103
|
+
quality?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Image format
|
|
106
|
+
*/
|
|
107
|
+
format?: 'png' | 'jpeg';
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,iBAAiB;IAE3B,eAAe,2BAA2B;IAC1C,cAAc,0BAA0B;IACxC,iBAAiB,6BAA6B;IAC9C,iBAAiB,6BAA6B;IAC9C,eAAe,2BAA2B;IAG1C,eAAe,2BAA2B;IAC1C,gBAAgB,4BAA4B;IAC5C,gBAAgB,4BAA4B;IAG5C,YAAY,wBAAwB;IACpC,aAAa,yBAAyB;IAGtC,WAAW,uBAAuB;IAClC,eAAe,2BAA2B;IAC1C,eAAe,2BAA2B;IAC1C,YAAY,wBAAwB;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAE7C;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACzB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message types for communication between WebView and Native code
|
|
3
|
+
*/
|
|
4
|
+
export var CuoralMessageType;
|
|
5
|
+
(function (CuoralMessageType) {
|
|
6
|
+
// Screen Recording
|
|
7
|
+
CuoralMessageType["START_RECORDING"] = "CUORAL_START_RECORDING";
|
|
8
|
+
CuoralMessageType["STOP_RECORDING"] = "CUORAL_STOP_RECORDING";
|
|
9
|
+
CuoralMessageType["RECORDING_STARTED"] = "CUORAL_RECORDING_STARTED";
|
|
10
|
+
CuoralMessageType["RECORDING_STOPPED"] = "CUORAL_RECORDING_STOPPED";
|
|
11
|
+
CuoralMessageType["RECORDING_ERROR"] = "CUORAL_RECORDING_ERROR";
|
|
12
|
+
// Screenshot
|
|
13
|
+
CuoralMessageType["TAKE_SCREENSHOT"] = "CUORAL_TAKE_SCREENSHOT";
|
|
14
|
+
CuoralMessageType["SCREENSHOT_TAKEN"] = "CUORAL_SCREENSHOT_TAKEN";
|
|
15
|
+
CuoralMessageType["SCREENSHOT_ERROR"] = "CUORAL_SCREENSHOT_ERROR";
|
|
16
|
+
// Widget Communication
|
|
17
|
+
CuoralMessageType["WIDGET_READY"] = "CUORAL_WIDGET_READY";
|
|
18
|
+
CuoralMessageType["WIDGET_CLOSED"] = "CUORAL_WIDGET_CLOSED";
|
|
19
|
+
// File Upload
|
|
20
|
+
CuoralMessageType["UPLOAD_FILE"] = "CUORAL_UPLOAD_FILE";
|
|
21
|
+
CuoralMessageType["UPLOAD_PROGRESS"] = "CUORAL_UPLOAD_PROGRESS";
|
|
22
|
+
CuoralMessageType["UPLOAD_COMPLETE"] = "CUORAL_UPLOAD_COMPLETE";
|
|
23
|
+
CuoralMessageType["UPLOAD_ERROR"] = "CUORAL_UPLOAD_ERROR";
|
|
24
|
+
})(CuoralMessageType || (CuoralMessageType = {}));
|
package/dist/web.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import { CuoralPluginInterface } from './plugin';
|
|
3
|
+
import { RecordingOptions, RecordingState, ScreenshotOptions, ScreenshotData } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Web implementation (for testing in browser)
|
|
6
|
+
*/
|
|
7
|
+
export declare class CuoralPluginWeb extends WebPlugin implements CuoralPluginInterface {
|
|
8
|
+
private isRecording;
|
|
9
|
+
private recordingStartTime?;
|
|
10
|
+
startRecording(options?: RecordingOptions): Promise<{
|
|
11
|
+
success: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
stopRecording(): Promise<{
|
|
14
|
+
success: boolean;
|
|
15
|
+
filePath?: string;
|
|
16
|
+
duration?: number;
|
|
17
|
+
}>;
|
|
18
|
+
getRecordingState(): Promise<RecordingState>;
|
|
19
|
+
takeScreenshot(options?: ScreenshotOptions): Promise<ScreenshotData>;
|
|
20
|
+
isRecordingSupported(): Promise<{
|
|
21
|
+
supported: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
requestPermissions(): Promise<{
|
|
24
|
+
granted: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAU,YAAW,qBAAqB;IAC7E,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAE9B,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IA4BzE,aAAa,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA2BpF,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;IAS5C,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IA6CpE,oBAAoB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAKvD,kBAAkB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAI1D"}
|