@revrag-ai/embed-react-native 1.0.5 → 1.0.6
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/dist/commonjs/Event/onwid.js +70 -0
- package/dist/commonjs/NativeOnwid.js +5 -0
- package/dist/commonjs/button.json +1 -0
- package/dist/commonjs/component/OnwidButton.js +507 -0
- package/dist/commonjs/component/audiowave.js +153 -0
- package/dist/commonjs/component/voice.js +127 -0
- package/dist/commonjs/hooks/initialize.js +96 -0
- package/dist/commonjs/hooks/initialize.types.js +2 -0
- package/{lib/module → dist/commonjs}/hooks/initializelivekit.js +7 -4
- package/dist/commonjs/hooks/voiceAgent.js +353 -0
- package/dist/commonjs/hooks/voiceAgent.types.js +4 -0
- package/dist/commonjs/index.d.js +22 -0
- package/dist/commonjs/index.js +34 -0
- package/dist/commonjs/onwidApi/api.js +185 -0
- package/dist/commonjs/onwidApi/api.types.js +2 -0
- package/dist/commonjs/package.json +1 -0
- package/dist/commonjs/store.key.js +38 -0
- package/dist/commonjs/style/onwidButton.style.js +243 -0
- package/dist/commonjs/utils/reanimatedHelpers.js +94 -0
- package/dist/commonjs/utils/utils.js +2 -0
- package/dist/module/Event/onwid.js +70 -0
- package/dist/module/NativeOnwid.js +5 -0
- package/dist/module/button.json +1 -0
- package/dist/module/component/OnwidButton.js +507 -0
- package/dist/module/component/audiowave.js +153 -0
- package/dist/module/component/voice.js +127 -0
- package/dist/module/hooks/initialize.js +96 -0
- package/dist/module/hooks/initialize.types.js +2 -0
- package/dist/module/hooks/initializelivekit.js +17 -0
- package/dist/module/hooks/voiceAgent.js +353 -0
- package/dist/module/hooks/voiceAgent.types.js +4 -0
- package/dist/module/index.d.js +22 -0
- package/dist/module/index.js +34 -0
- package/dist/module/onwidApi/api.js +185 -0
- package/dist/module/onwidApi/api.types.js +2 -0
- package/dist/module/store.key.js +38 -0
- package/dist/module/style/onwidButton.style.js +243 -0
- package/dist/module/utils/reanimatedHelpers.js +94 -0
- package/dist/module/utils/utils.js +2 -0
- package/{lib → dist}/typescript/Event/onwid.d.ts +1 -0
- package/{lib → dist}/typescript/NativeOnwid.d.ts +1 -0
- package/{lib → dist}/typescript/component/OnwidButton.d.ts +1 -0
- package/{lib → dist}/typescript/component/audiowave.d.ts +1 -0
- package/{lib → dist}/typescript/component/voice.d.ts +1 -0
- package/{lib → dist}/typescript/hooks/initialize.d.ts +1 -0
- package/{lib → dist}/typescript/hooks/initialize.types.d.ts +1 -0
- package/{lib → dist}/typescript/hooks/initializelivekit.d.ts +1 -0
- package/{lib → dist}/typescript/hooks/voiceAgent.d.ts +1 -0
- package/{lib → dist}/typescript/hooks/voiceAgent.types.d.ts +1 -0
- package/{lib → dist}/typescript/index.d.ts +3 -3
- package/{lib → dist}/typescript/onwidApi/api.d.ts +1 -0
- package/{lib → dist}/typescript/onwidApi/api.types.d.ts +1 -0
- package/{lib → dist}/typescript/store.key.d.ts +1 -0
- package/{lib → dist}/typescript/style/onwidButton.style.d.ts +1 -0
- package/{lib → dist}/typescript/utils/reanimatedHelpers.d.ts +1 -0
- package/dist/typescript/utils/utils.d.ts +1 -0
- package/package.json +29 -21
- package/lib/index.d.ts +0 -77
- package/lib/module/Event/onwid.js +0 -74
- package/lib/module/NativeOnwid.js +0 -4
- package/lib/module/component/OnwidButton.js +0 -366
- package/lib/module/component/audiowave.js +0 -137
- package/lib/module/component/voice.js +0 -103
- package/lib/module/hooks/initialize.js +0 -92
- package/lib/module/hooks/initialize.types.js +0 -2
- package/lib/module/hooks/voiceAgent.js +0 -334
- package/lib/module/hooks/voiceAgent.types.js +0 -2
- package/lib/module/index.js +0 -61
- package/lib/module/onwidApi/api.js +0 -184
- package/lib/module/onwidApi/api.types.js +0 -2
- package/lib/module/store.key.js +0 -47
- package/lib/module/style/onwidButton.style.js +0 -230
- package/lib/module/utils/reanimatedHelpers.js +0 -87
- package/lib/module/utils/utils.js +0 -1
- package/lib/typescript/utils/utils.d.ts +0 -0
package/package.json
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revrag-ai/embed-react-native",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Voice Agent SDK for React Native - AI-powered voice communication with real-time speech processing",
|
|
5
|
-
"main": "./
|
|
6
|
-
"
|
|
5
|
+
"main": "./dist/commonjs/index.js",
|
|
6
|
+
"module": "./dist/module/index.js",
|
|
7
|
+
"types": "./dist/typescript/index.d.ts",
|
|
7
8
|
"typesVersions": {
|
|
8
9
|
"*": {
|
|
9
|
-
"*": ["./
|
|
10
|
+
"*": ["./dist/typescript/*"]
|
|
10
11
|
}
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
|
14
|
-
"types": "./
|
|
15
|
-
"import": "./
|
|
16
|
-
"require": "./
|
|
17
|
-
"default": "./
|
|
15
|
+
"types": "./dist/typescript/index.d.ts",
|
|
16
|
+
"import": "./dist/module/index.js",
|
|
17
|
+
"require": "./dist/commonjs/index.js",
|
|
18
|
+
"default": "./dist/module/index.js"
|
|
18
19
|
},
|
|
19
20
|
"./package.json": "./package.json"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
22
|
-
"
|
|
23
|
+
"dist",
|
|
23
24
|
"android",
|
|
24
25
|
"ios",
|
|
25
26
|
"cpp",
|
|
@@ -27,9 +28,9 @@
|
|
|
27
28
|
"scripts",
|
|
28
29
|
"*.podspec",
|
|
29
30
|
"react-native.config.js",
|
|
30
|
-
"!
|
|
31
|
-
"!
|
|
32
|
-
"!
|
|
31
|
+
"!dist/**/*.map",
|
|
32
|
+
"!dist/**/*.test.*",
|
|
33
|
+
"!dist/**/*.spec.*",
|
|
33
34
|
"!ios/build",
|
|
34
35
|
"!android/build",
|
|
35
36
|
"!android/gradle",
|
|
@@ -47,17 +48,17 @@
|
|
|
47
48
|
"test": "jest",
|
|
48
49
|
"typecheck": "tsc",
|
|
49
50
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
50
|
-
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build
|
|
51
|
-
"prepare": "
|
|
52
|
-
"
|
|
51
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build dist",
|
|
52
|
+
"prepare": "bob build",
|
|
53
|
+
"build": "bob build",
|
|
53
54
|
"fix-js": "node fix-js-files.js",
|
|
54
55
|
"verify-setup": "node scripts/verify-setup.js",
|
|
55
|
-
"prepublishOnly": "
|
|
56
|
+
"prepublishOnly": "bob build && yarn fix-js",
|
|
56
57
|
"release": "release-it --only-version",
|
|
57
58
|
"protect": "node -e \"const crypto = require('crypto'); const fs = require('fs'); const config = { hash: crypto.randomBytes(32).toString('hex'), createdAt: new Date().toISOString(), note: 'Protected build', version: require('./package.json').version }; fs.writeFileSync('.onwid-security.json', JSON.stringify(config, null, 2)); console.log('✅ Code protected');\"",
|
|
58
|
-
"publish:safe": "yarn clean &&
|
|
59
|
-
"publish:beta": "yarn clean &&
|
|
60
|
-
"publish:alpha": "yarn clean &&
|
|
59
|
+
"publish:safe": "yarn clean && bob build && yarn fix-js && yarn protect && npm publish --access public",
|
|
60
|
+
"publish:beta": "yarn clean && bob build && yarn fix-js && yarn protect && npm publish --access public --tag beta",
|
|
61
|
+
"publish:alpha": "yarn clean && bob build && yarn fix-js && yarn protect && npm publish --access public --tag alpha"
|
|
61
62
|
},
|
|
62
63
|
"keywords": [
|
|
63
64
|
"react-native",
|
|
@@ -137,7 +138,7 @@
|
|
|
137
138
|
"preset": "react-native",
|
|
138
139
|
"modulePathIgnorePatterns": [
|
|
139
140
|
"<rootDir>/example/node_modules",
|
|
140
|
-
"<rootDir>/
|
|
141
|
+
"<rootDir>/dist/"
|
|
141
142
|
]
|
|
142
143
|
},
|
|
143
144
|
"commitlint": {
|
|
@@ -173,11 +174,18 @@
|
|
|
173
174
|
},
|
|
174
175
|
"react-native-builder-bob": {
|
|
175
176
|
"source": "src",
|
|
176
|
-
"output": "
|
|
177
|
+
"output": "dist",
|
|
177
178
|
"targets": [
|
|
179
|
+
[
|
|
180
|
+
"commonjs",
|
|
181
|
+
{
|
|
182
|
+
"configFile": true
|
|
183
|
+
}
|
|
184
|
+
],
|
|
178
185
|
[
|
|
179
186
|
"module",
|
|
180
187
|
{
|
|
188
|
+
"configFile": true,
|
|
181
189
|
"esm": true
|
|
182
190
|
}
|
|
183
191
|
],
|
package/lib/index.d.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file index.d.ts
|
|
3
|
-
* @description TypeScript declarations for the Onwid React Native library.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ConnectionState, Room } from 'livekit-client';
|
|
7
|
-
import { RefObject } from 'react';
|
|
8
|
-
|
|
9
|
-
// Component declarations
|
|
10
|
-
export declare function OnwidButton(): JSX.Element;
|
|
11
|
-
|
|
12
|
-
// Hook type declarations
|
|
13
|
-
export interface UseInitializeProps {
|
|
14
|
-
apiKey: string;
|
|
15
|
-
agentId?: string;
|
|
16
|
-
onwidUrl?: string;
|
|
17
|
-
metadata?: any;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface UseVoiceAgentReturn {
|
|
21
|
-
initializeVoiceAgent: () => Promise<void>;
|
|
22
|
-
isLoading: boolean;
|
|
23
|
-
error: string | null;
|
|
24
|
-
tokenDetails: any;
|
|
25
|
-
endCall: () => Promise<void>;
|
|
26
|
-
room: Room;
|
|
27
|
-
roomRef: RefObject<Room>;
|
|
28
|
-
isMicMuted: boolean;
|
|
29
|
-
muteMic: () => void;
|
|
30
|
-
unmuteMic: () => void;
|
|
31
|
-
connectionState: ConnectionState;
|
|
32
|
-
cleanup: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Hook declarations
|
|
36
|
-
export declare const useInitialize: (props: UseInitializeProps) => void;
|
|
37
|
-
export declare const useVoiceAgent: () => UseVoiceAgentReturn;
|
|
38
|
-
|
|
39
|
-
// API type declarations
|
|
40
|
-
export interface ApiResponse<T> {
|
|
41
|
-
success: boolean;
|
|
42
|
-
data?: T;
|
|
43
|
-
error?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface RegisterRequest {
|
|
47
|
-
apiKey: string;
|
|
48
|
-
onwidUrl: string;
|
|
49
|
-
metadata?: Record<string, any>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface TokenDetails {
|
|
53
|
-
token: string;
|
|
54
|
-
expiresAt: number;
|
|
55
|
-
apiKey: string;
|
|
56
|
-
config: Record<string, any>;
|
|
57
|
-
server_url: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface UpdateDataRequest {
|
|
61
|
-
eventKey: string;
|
|
62
|
-
data: Record<string, any>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Event system declarations
|
|
66
|
-
export enum EventKeys {
|
|
67
|
-
USER_DATA = 'user_data',
|
|
68
|
-
SCREEN_STATE = 'state_data',
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export declare class OnWid {
|
|
72
|
-
Event(eventKey: string, data: any): Promise<void>;
|
|
73
|
-
on(eventKey: EventKeys, callback: (data: any) => void): void;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export declare const onwid: OnWid;
|
|
77
|
-
export declare const registerAgent: any;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EventKeys = void 0;
|
|
4
|
-
const store_key_1 = require("../store.key");
|
|
5
|
-
const api_1 = require("../onwidApi/api");
|
|
6
|
-
// Predefined event keys
|
|
7
|
-
var EventKeys;
|
|
8
|
-
(function (EventKeys) {
|
|
9
|
-
EventKeys["USER_DATA"] = "user_data";
|
|
10
|
-
EventKeys["SCREEN_STATE"] = "state_data";
|
|
11
|
-
})(EventKeys || (exports.EventKeys = EventKeys = {}));
|
|
12
|
-
class OnWid {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.events = {};
|
|
15
|
-
}
|
|
16
|
-
// Automatically adds a default listener if none exists
|
|
17
|
-
ensureDefaultListener(eventKey) {
|
|
18
|
-
if (!this.events[eventKey]) {
|
|
19
|
-
this.events[eventKey] = [
|
|
20
|
-
(data) => {
|
|
21
|
-
console.log(`[Default] Event handled for ${eventKey}:`, data);
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
async Event(eventKey, data) {
|
|
27
|
-
var _a;
|
|
28
|
-
if (!Object.values(EventKeys).includes(eventKey)) {
|
|
29
|
-
console.error(`Invalid event key: ${eventKey}`);
|
|
30
|
-
throw new Error(`Invalid event key: ${eventKey}. Must be one of: ${Object.values(EventKeys).join(', ')}`);
|
|
31
|
-
}
|
|
32
|
-
const key = eventKey;
|
|
33
|
-
if (key !== EventKeys.USER_DATA) {
|
|
34
|
-
const userIdentity = await (0, store_key_1.getAgentData)(EventKeys.USER_DATA);
|
|
35
|
-
if (userIdentity) {
|
|
36
|
-
data.app_user_id = userIdentity.app_user_id;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
throw new Error('User identity not found');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Ensure a default listener is registered if not already
|
|
43
|
-
this.ensureDefaultListener(key);
|
|
44
|
-
console.log('response,updateUserDatniuioioioa');
|
|
45
|
-
// Trigger API call
|
|
46
|
-
try {
|
|
47
|
-
const apiService = api_1.APIService.getInstance();
|
|
48
|
-
const response = await apiService.updateUserData({
|
|
49
|
-
eventKey: key,
|
|
50
|
-
data,
|
|
51
|
-
});
|
|
52
|
-
console.log('response,updateUserData', response);
|
|
53
|
-
if (!response.success) {
|
|
54
|
-
console.error('Failed to trigger API for event:', eventKey);
|
|
55
|
-
}
|
|
56
|
-
(0, store_key_1.setAgentData)(data, key);
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
console.error('Error triggering API:', error);
|
|
60
|
-
}
|
|
61
|
-
// Trigger event listeners
|
|
62
|
-
(_a = this.events[key]) === null || _a === void 0 ? void 0 : _a.forEach((callback) => callback(data));
|
|
63
|
-
}
|
|
64
|
-
// Still allow custom listeners (optional)
|
|
65
|
-
on(eventKey, callback) {
|
|
66
|
-
var _a;
|
|
67
|
-
if (!this.events[eventKey]) {
|
|
68
|
-
this.events[eventKey] = [];
|
|
69
|
-
}
|
|
70
|
-
(_a = this.events[eventKey]) === null || _a === void 0 ? void 0 : _a.push(callback);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const onwid = new OnWid();
|
|
74
|
-
exports.default = onwid;
|
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.OnwidButton = OnwidButton;
|
|
7
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
-
const lottie_react_native_1 = __importDefault(require("lottie-react-native"));
|
|
9
|
-
const react_1 = require("react");
|
|
10
|
-
const react_native_1 = require("react-native");
|
|
11
|
-
const react_native_gesture_handler_1 = require("react-native-gesture-handler");
|
|
12
|
-
const react_native_linear_gradient_1 = __importDefault(require("react-native-linear-gradient"));
|
|
13
|
-
const voice_1 = __importDefault(require("../component/voice"));
|
|
14
|
-
const voiceAgent_1 = require("../hooks/voiceAgent");
|
|
15
|
-
const store_key_1 = require("../store.key");
|
|
16
|
-
const onwidButton_style_1 = require("../style/onwidButton.style");
|
|
17
|
-
const reanimatedHelpers_1 = require("../utils/reanimatedHelpers");
|
|
18
|
-
const audiowave_1 = require("./audiowave");
|
|
19
|
-
// Get reanimated API with fallbacks
|
|
20
|
-
const { useSharedValue, useAnimatedStyle, withTiming, withSpring, withRepeat, withSequence, runOnJS, Easing, Animated, isAvailable: isReanimatedAvailable, } = (0, reanimatedHelpers_1.getReanimatedAPI)();
|
|
21
|
-
// Show warning if reanimated is not available
|
|
22
|
-
if (!isReanimatedAvailable) {
|
|
23
|
-
(0, reanimatedHelpers_1.showReanimatedSetupError)();
|
|
24
|
-
}
|
|
25
|
-
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = react_native_1.Dimensions.get('window');
|
|
26
|
-
const BUTTON_WIDTH = 60;
|
|
27
|
-
const EXPANDED_WIDTH = SCREEN_WIDTH * 0.9;
|
|
28
|
-
const BUTTON_HEIGHT = 60;
|
|
29
|
-
const GRADIENT_COLORS = ['#1E0844', '#B391F3'];
|
|
30
|
-
// Define mic icons as base64 images for portability
|
|
31
|
-
const MIC_ON_ICON = 'https://revrag-dev.s3.ap-south-1.amazonaws.com/Avatars/Mute+button.png';
|
|
32
|
-
const MIC_OFF_ICON = 'https://revrag-dev.s3.ap-south-1.amazonaws.com/Avatars/unmute.png';
|
|
33
|
-
// Add end call icon
|
|
34
|
-
const END_CALL_ICON = 'https://revrag-dev.s3.ap-south-1.amazonaws.com/Avatars/end+button.png';
|
|
35
|
-
const AMPLIFY_ANIMATION = 'https://revrag-dev.s3.ap-south-1.amazonaws.com/Avatars/amplify.json';
|
|
36
|
-
/**
|
|
37
|
-
* Default styles configuration for the button
|
|
38
|
-
*/
|
|
39
|
-
const defaultStyles = {
|
|
40
|
-
buttonWidth: 60,
|
|
41
|
-
buttonHeight: 60,
|
|
42
|
-
borderRadius: 100,
|
|
43
|
-
marginBottom: 20,
|
|
44
|
-
spacing: {
|
|
45
|
-
SMALL: 10,
|
|
46
|
-
MEDIUM: 15,
|
|
47
|
-
LARGE: 25,
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* OnwidButton Component
|
|
52
|
-
*
|
|
53
|
-
* A floating action button that can be dragged around the screen and expanded to show additional content.
|
|
54
|
-
* Features include:
|
|
55
|
-
* - Draggable functionality
|
|
56
|
-
* - Expandable menu
|
|
57
|
-
* - Animated transitions
|
|
58
|
-
* - Gradient background
|
|
59
|
-
* - Customizable styling
|
|
60
|
-
*
|
|
61
|
-
* @component
|
|
62
|
-
* @example
|
|
63
|
-
* ```tsx
|
|
64
|
-
* <OnwidButton
|
|
65
|
-
* isOpen={false}
|
|
66
|
-
* onPress={(isOpen) => console.log('Button pressed:', isOpen)}
|
|
67
|
-
* menuComponent={<YourMenuComponent />}
|
|
68
|
-
* />
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
function OnwidButton() {
|
|
72
|
-
var _a;
|
|
73
|
-
const { initializeVoiceAgent, tokenDetails, endCall, isLoading, isMicMuted, muteMic, unmuteMic, connectionState, roomRef, } = (0, voiceAgent_1.useVoiceAgent)();
|
|
74
|
-
// State management
|
|
75
|
-
const [configData, setConfigData] = (0, react_1.useState)(null);
|
|
76
|
-
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
77
|
-
const [callDuration, setCallDuration] = (0, react_1.useState)(0);
|
|
78
|
-
const timerRef = (0, react_1.useRef)(null);
|
|
79
|
-
const lottieRef = (0, react_1.useRef)(null);
|
|
80
|
-
console.log('roomRef', (_a = roomRef.current) === null || _a === void 0 ? void 0 : _a.localParticipant);
|
|
81
|
-
// Animation values
|
|
82
|
-
const isPressed = useSharedValue(false);
|
|
83
|
-
const offset = useSharedValue({ x: 0, y: 0 });
|
|
84
|
-
const start = useSharedValue({ x: 0, y: 0 });
|
|
85
|
-
const menuAnimation = useSharedValue(0);
|
|
86
|
-
const buttonWidth = useSharedValue(BUTTON_WIDTH);
|
|
87
|
-
const buttonScale = useSharedValue(1);
|
|
88
|
-
// Styles
|
|
89
|
-
const styles = (0, onwidButton_style_1.createOnwidButtonStyles)(defaultStyles);
|
|
90
|
-
const [isAutoOpen, setIsAutoOpen] = (0, react_1.useState)(false);
|
|
91
|
-
(0, react_1.useEffect)(() => {
|
|
92
|
-
const autoOpenTimer = setTimeout(() => {
|
|
93
|
-
if (!isOpen) {
|
|
94
|
-
console.log('autoOpenTimer', isOpen);
|
|
95
|
-
setIsAutoOpen(true);
|
|
96
|
-
}
|
|
97
|
-
}, 15000); // 15 seconds
|
|
98
|
-
return () => {
|
|
99
|
-
clearTimeout(autoOpenTimer);
|
|
100
|
-
};
|
|
101
|
-
}, [isOpen]);
|
|
102
|
-
/**
|
|
103
|
-
* Fetch agent configuration data
|
|
104
|
-
*/
|
|
105
|
-
(0, react_1.useEffect)(() => {
|
|
106
|
-
const fetchAgentData = async () => {
|
|
107
|
-
try {
|
|
108
|
-
const data = await (0, store_key_1.getAgentData)('@config_data');
|
|
109
|
-
setConfigData(data === null || data === void 0 ? void 0 : data.ui_config);
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
console.error('Error retrieving agent data:', error);
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
fetchAgentData();
|
|
116
|
-
}, []);
|
|
117
|
-
/**
|
|
118
|
-
* Set up a timer to track call duration when connected
|
|
119
|
-
*/
|
|
120
|
-
(0, react_1.useEffect)(() => {
|
|
121
|
-
if (connectionState === 'connected' && !timerRef.current) {
|
|
122
|
-
timerRef.current = setInterval(() => {
|
|
123
|
-
setCallDuration((prev) => prev + 1);
|
|
124
|
-
}, 1000);
|
|
125
|
-
}
|
|
126
|
-
else if (connectionState !== 'connected' && timerRef.current) {
|
|
127
|
-
clearInterval(timerRef.current);
|
|
128
|
-
timerRef.current = null;
|
|
129
|
-
// If we were previously connected and now disconnected, show an error
|
|
130
|
-
if (callDuration > 0) {
|
|
131
|
-
console.log('Call unexpectedly disconnected after', callDuration, 'seconds');
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return () => {
|
|
135
|
-
if (timerRef.current) {
|
|
136
|
-
clearInterval(timerRef.current);
|
|
137
|
-
timerRef.current = null;
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
}, [connectionState, callDuration]);
|
|
141
|
-
/**
|
|
142
|
-
* Handle menu animation and button width transitions
|
|
143
|
-
*/
|
|
144
|
-
(0, react_1.useEffect)(() => {
|
|
145
|
-
menuAnimation.value = withTiming(isOpen ? 0.8 : 0, {
|
|
146
|
-
duration: 300,
|
|
147
|
-
});
|
|
148
|
-
buttonWidth.value = withTiming(isOpen ? EXPANDED_WIDTH : BUTTON_WIDTH);
|
|
149
|
-
}, [isOpen, menuAnimation, buttonWidth]);
|
|
150
|
-
// Add breathing animation when button is closed but isAutoOpen is true
|
|
151
|
-
(0, react_1.useEffect)(() => {
|
|
152
|
-
if (!isOpen && isAutoOpen) {
|
|
153
|
-
// Start breathing animation with faster speed
|
|
154
|
-
buttonScale.value = withRepeat(withSequence(withTiming(1.1, {
|
|
155
|
-
duration: 1500, // Reduced from 1000ms to 600ms
|
|
156
|
-
easing: Easing.inOut(Easing.ease),
|
|
157
|
-
}), withTiming(1, {
|
|
158
|
-
duration: 1500, // Reduced from 1000ms to 600ms
|
|
159
|
-
easing: Easing.inOut(Easing.ease),
|
|
160
|
-
})), -1, // Infinite repeat
|
|
161
|
-
false // Don't reverse
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
// Reset animation
|
|
166
|
-
buttonScale.value = withTiming(1, { duration: 300 });
|
|
167
|
-
}
|
|
168
|
-
}, [isOpen, isAutoOpen]);
|
|
169
|
-
/**
|
|
170
|
-
* Animated styles for the button
|
|
171
|
-
*/
|
|
172
|
-
const animatedStyles = useAnimatedStyle(() => {
|
|
173
|
-
const maxX = SCREEN_WIDTH - (isOpen ? EXPANDED_WIDTH : BUTTON_WIDTH) - 35;
|
|
174
|
-
const clampedX = Math.min(Math.max(offset.value.x, -maxX), 0);
|
|
175
|
-
return {
|
|
176
|
-
width: buttonWidth.value,
|
|
177
|
-
height: BUTTON_HEIGHT,
|
|
178
|
-
transform: [
|
|
179
|
-
{ translateX: clampedX },
|
|
180
|
-
{ translateY: offset.value.y },
|
|
181
|
-
{ scale: withSpring(isPressed.value ? 0.95 : buttonScale.value) },
|
|
182
|
-
],
|
|
183
|
-
justifyContent: isOpen ? 'space-between' : 'flex-start',
|
|
184
|
-
overflow: 'hidden',
|
|
185
|
-
};
|
|
186
|
-
});
|
|
187
|
-
/**
|
|
188
|
-
* Animated styles for the text
|
|
189
|
-
*/
|
|
190
|
-
const animatedTextStyles = useAnimatedStyle(() => {
|
|
191
|
-
const maxX = SCREEN_WIDTH;
|
|
192
|
-
const clampedX = Math.min(Math.max(offset.value.x, -maxX), 0);
|
|
193
|
-
return {
|
|
194
|
-
transform: [
|
|
195
|
-
{ translateX: clampedX },
|
|
196
|
-
{ translateY: offset.value.y },
|
|
197
|
-
{ scale: withSpring(isPressed.value ? 1 : 1) },
|
|
198
|
-
],
|
|
199
|
-
};
|
|
200
|
-
});
|
|
201
|
-
/**
|
|
202
|
-
* Pan gesture handler for drag functionality
|
|
203
|
-
*/
|
|
204
|
-
const gesture = react_native_gesture_handler_1.Gesture.Pan()
|
|
205
|
-
.onBegin(() => {
|
|
206
|
-
isPressed.value = true;
|
|
207
|
-
if (isAutoOpen) {
|
|
208
|
-
runOnJS(setIsAutoOpen)(false);
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
.onUpdate((e) => {
|
|
212
|
-
const maxX = SCREEN_WIDTH - (isOpen ? EXPANDED_WIDTH : BUTTON_WIDTH) - 0;
|
|
213
|
-
const newX = Math.min(Math.max(e.translationX + start.value.x, -maxX), 0);
|
|
214
|
-
const maxY = SCREEN_HEIGHT - 150;
|
|
215
|
-
const newY = Math.min(Math.max(e.translationY + start.value.y, -maxY), 0);
|
|
216
|
-
offset.value = {
|
|
217
|
-
x: newX,
|
|
218
|
-
y: newY,
|
|
219
|
-
};
|
|
220
|
-
})
|
|
221
|
-
.onEnd(() => {
|
|
222
|
-
start.value = {
|
|
223
|
-
x: offset.value.x,
|
|
224
|
-
y: offset.value.y,
|
|
225
|
-
};
|
|
226
|
-
})
|
|
227
|
-
.onFinalize(() => {
|
|
228
|
-
isPressed.value = false;
|
|
229
|
-
});
|
|
230
|
-
/**
|
|
231
|
-
* Handle button press events
|
|
232
|
-
*/
|
|
233
|
-
const handlePress = () => {
|
|
234
|
-
console.log('handlePress', isOpen);
|
|
235
|
-
console.log('isAutoOpen', isAutoOpen);
|
|
236
|
-
// cleanup();
|
|
237
|
-
setIsOpen(!isOpen);
|
|
238
|
-
setIsAutoOpen(false);
|
|
239
|
-
};
|
|
240
|
-
const handleStartCall = async () => {
|
|
241
|
-
setCallDuration(0);
|
|
242
|
-
await initializeVoiceAgent();
|
|
243
|
-
};
|
|
244
|
-
/**
|
|
245
|
-
* Render the button icon/animation
|
|
246
|
-
*/
|
|
247
|
-
const remoteSource = (0, react_1.useMemo)(() => ({
|
|
248
|
-
uri: (configData === null || configData === void 0 ? void 0 : configData.icon_animation) || AMPLIFY_ANIMATION,
|
|
249
|
-
}), [configData === null || configData === void 0 ? void 0 : configData.icon_animation]);
|
|
250
|
-
const renderIcon = () => {
|
|
251
|
-
// When isAutoOpen is true, we don't play the Lottie animation
|
|
252
|
-
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { children: (0, jsx_runtime_1.jsx)(lottie_react_native_1.default, { ref: lottieRef, source: remoteSource, autoPlay: true, loop: true, style: styles.iconImage, enableMergePathsAndroidForKitKatAndAbove: true, enableSafeModeAndroid: true }) }));
|
|
253
|
-
};
|
|
254
|
-
const handleConnected = () => {
|
|
255
|
-
console.log('Call connected');
|
|
256
|
-
};
|
|
257
|
-
const handleEndCall = async () => {
|
|
258
|
-
setIsOpen(false);
|
|
259
|
-
if (timerRef.current) {
|
|
260
|
-
clearInterval(timerRef.current);
|
|
261
|
-
timerRef.current = null;
|
|
262
|
-
}
|
|
263
|
-
setCallDuration(0);
|
|
264
|
-
await endCall();
|
|
265
|
-
};
|
|
266
|
-
const handleMicToggle = () => {
|
|
267
|
-
if (isMicMuted) {
|
|
268
|
-
unmuteMic();
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
muteMic();
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
// Format duration to MM:SS
|
|
275
|
-
const formatDuration = (seconds) => {
|
|
276
|
-
const minutes = Math.floor(seconds / 60);
|
|
277
|
-
const remainingSeconds = seconds % 60;
|
|
278
|
-
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds
|
|
279
|
-
.toString()
|
|
280
|
-
.padStart(2, '0')}`;
|
|
281
|
-
};
|
|
282
|
-
// Get the status text based on current state
|
|
283
|
-
const getStatusText = () => {
|
|
284
|
-
if (isLoading) {
|
|
285
|
-
return 'Connecting...';
|
|
286
|
-
}
|
|
287
|
-
else if (tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.token) {
|
|
288
|
-
return `Call Duration: ${formatDuration(callDuration)}`;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
return (configData === null || configData === void 0 ? void 0 : configData.agent_type) || 'Onboarding Agent';
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
if (!configData)
|
|
295
|
-
return null;
|
|
296
|
-
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.container, children: [isAutoOpen && !isOpen && ((0, jsx_runtime_1.jsx)(Animated.View, { style: [
|
|
297
|
-
animatedTextStyles,
|
|
298
|
-
{
|
|
299
|
-
position: 'absolute',
|
|
300
|
-
borderRadius: 5,
|
|
301
|
-
paddingVertical: 2,
|
|
302
|
-
paddingHorizontal: 10,
|
|
303
|
-
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
304
|
-
bottom: BUTTON_HEIGHT + 40,
|
|
305
|
-
// right: Math.abs(offset.value.x) + BUTTON_WIDTH + 0,
|
|
306
|
-
},
|
|
307
|
-
], children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: { color: 'white', fontSize: 10, fontWeight: '500' }, children: (configData === null || configData === void 0 ? void 0 : configData.popup_description) || 'Revrag' }) })), (0, jsx_runtime_1.jsx)(react_native_gesture_handler_1.GestureDetector, { gesture: gesture, children: (0, jsx_runtime_1.jsx)(Animated.View, { style: [
|
|
308
|
-
styles.button,
|
|
309
|
-
animatedStyles,
|
|
310
|
-
styles.buttonContent,
|
|
311
|
-
{
|
|
312
|
-
pointerEvents: 'auto',
|
|
313
|
-
},
|
|
314
|
-
], children: (0, jsx_runtime_1.jsxs)(react_native_linear_gradient_1.default, { colors: (configData === null || configData === void 0 ? void 0 : configData.gradient) || GRADIENT_COLORS, start: { x: 0, y: 0 }, end: { x: 1, y: 0 }, style: [
|
|
315
|
-
styles.linearGradient,
|
|
316
|
-
{
|
|
317
|
-
width: '100%',
|
|
318
|
-
flexDirection: 'row',
|
|
319
|
-
alignItems: 'center',
|
|
320
|
-
paddingHorizontal: 0,
|
|
321
|
-
paddingLeft: 0,
|
|
322
|
-
paddingRight: isOpen ? 5 : 0,
|
|
323
|
-
},
|
|
324
|
-
], angle: 0, angleCenter: { x: 0.5, y: 0.5 }, children: [(tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.token) && ((0, jsx_runtime_1.jsx)(voice_1.default, { url: tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.server_url, token: tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.token, onDisconnected: handleEndCall, roomRef: roomRef, onConnected: handleConnected })), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
|
|
325
|
-
styles.rowContainer,
|
|
326
|
-
{
|
|
327
|
-
flexShrink: 0,
|
|
328
|
-
width: BUTTON_WIDTH,
|
|
329
|
-
padding: 0,
|
|
330
|
-
margin: 0,
|
|
331
|
-
},
|
|
332
|
-
], children: (0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handlePress, style: styles.pressable, children: renderIcon() }) }), isOpen && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
|
|
333
|
-
flex: 1,
|
|
334
|
-
flexDirection: 'row',
|
|
335
|
-
height: BUTTON_HEIGHT - 10,
|
|
336
|
-
marginLeft: 0,
|
|
337
|
-
marginRight: 0,
|
|
338
|
-
}, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
|
|
339
|
-
flex: 1,
|
|
340
|
-
justifyContent: 'center',
|
|
341
|
-
alignItems: 'flex-start',
|
|
342
|
-
paddingLeft: 8,
|
|
343
|
-
paddingRight: 4,
|
|
344
|
-
}, children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
|
|
345
|
-
styles.agentNameText,
|
|
346
|
-
{ flexShrink: 1, textAlign: 'left' },
|
|
347
|
-
], children: (configData === null || configData === void 0 ? void 0 : configData.agent_name) || 'Revrag' }), (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
|
|
348
|
-
styles.statusText,
|
|
349
|
-
{ flexShrink: 1, textAlign: 'left' },
|
|
350
|
-
], children: getStatusText() })] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: {
|
|
351
|
-
flex: 1,
|
|
352
|
-
justifyContent: 'center',
|
|
353
|
-
alignItems: 'center',
|
|
354
|
-
paddingHorizontal: 4,
|
|
355
|
-
}, children: (0, jsx_runtime_1.jsx)(audiowave_1.WaveformVisualizer, { roomRef: roomRef }) }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
|
|
356
|
-
flex: 1,
|
|
357
|
-
justifyContent: 'center',
|
|
358
|
-
alignItems: 'flex-end',
|
|
359
|
-
paddingLeft: 4,
|
|
360
|
-
paddingRight: 8,
|
|
361
|
-
}, children: [!(tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.token) && ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleStartCall, style: styles.startCallButton, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: styles.startCallText, children: (configData === null || configData === void 0 ? void 0 : configData.start_call_text) || 'Start Call' }) })), (tokenDetails === null || tokenDetails === void 0 ? void 0 : tokenDetails.token) && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.buttonContainer], children: [(0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { style: styles.muteButton, onPress: handleMicToggle, children: (0, jsx_runtime_1.jsx)(react_native_1.Image, { source: {
|
|
362
|
-
uri: isMicMuted ? MIC_OFF_ICON : MIC_ON_ICON,
|
|
363
|
-
}, style: styles.buttonImage }) }), (0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleEndCall, style: styles.endCallButton, children: (0, jsx_runtime_1.jsx)(react_native_1.Image, { source: { uri: END_CALL_ICON }, style: styles.buttonImage }) })] }))] })] }))] }) }) })] }));
|
|
364
|
-
}
|
|
365
|
-
// Export default for easier imports
|
|
366
|
-
exports.default = OnwidButton;
|