agora-appbuilder-core 4.1.12 → 4.1.13-beta.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/package.json +1 -1
- package/template/customization-api/temp.ts +9 -1
- package/template/defaultConfig.js +2 -2
- package/template/package.json +1 -1
- package/template/src/components/Controls.tsx +9 -1
- package/template/src/components/whiteboard/FastBoardView.tsx +227 -0
- package/template/src/components/whiteboard/StrokeWidthTool.tsx +5 -1
- package/template/src/components/whiteboard/WhiteboardButton.tsx +9 -1
- package/template/src/components/whiteboard/WhiteboardCanvas.tsx +9 -1
- package/template/src/components/whiteboard/WhiteboardConfigure.tsx +95 -215
- package/template/src/components/whiteboard/WhiteboardCursor.tsx +17 -9
- package/template/src/components/whiteboard/WhiteboardToolBox.tsx +15 -1
- package/template/src/components/whiteboard/WhiteboardView.tsx +9 -1
- package/template/src/components/whiteboard/WhiteboardWidget.tsx +4 -1
- package/template/src/components/whiteboard/WhiteboardWrapper.tsx +3 -2
package/package.json
CHANGED
|
@@ -16,7 +16,15 @@ import {useCaption} from '../src/subComponents/caption/useCaption';
|
|
|
16
16
|
import useMuteToggleLocal, {
|
|
17
17
|
MUTE_LOCAL_TYPE,
|
|
18
18
|
} from '../src/utils/useMuteToggleLocal';
|
|
19
|
-
import {RoomPhase} from 'white-web-sdk';
|
|
19
|
+
// import {RoomPhase} from 'white-web-sdk';
|
|
20
|
+
// Commented out for fastboard migration
|
|
21
|
+
enum RoomPhase {
|
|
22
|
+
Connecting = 'connecting',
|
|
23
|
+
Connected = 'connected',
|
|
24
|
+
Reconnecting = 'reconnecting',
|
|
25
|
+
Disconnecting = 'disconnecting',
|
|
26
|
+
Disconnected = 'disconnected',
|
|
27
|
+
}
|
|
20
28
|
import {useScreenContext} from '../src/components/contexts/ScreenShareContext';
|
|
21
29
|
import {filterObject} from '../src/utils/index';
|
|
22
30
|
import {useToggleWhiteboard} from '../src/components/Controls';
|
|
@@ -77,8 +77,8 @@ const DefaultConfig = {
|
|
|
77
77
|
CHAT_ORG_NAME: '',
|
|
78
78
|
CHAT_APP_NAME: '',
|
|
79
79
|
CHAT_URL: '',
|
|
80
|
-
CLI_VERSION: '3.1.
|
|
81
|
-
CORE_VERSION: '4.1.
|
|
80
|
+
CLI_VERSION: '3.1.13-beta.1',
|
|
81
|
+
CORE_VERSION: '4.1.13-beta.1',
|
|
82
82
|
DISABLE_LANDSCAPE_MODE: false,
|
|
83
83
|
STT_AUTO_START: false,
|
|
84
84
|
CLOUD_RECORDING_AUTO_START: false,
|
package/template/package.json
CHANGED
|
@@ -82,7 +82,15 @@ import {
|
|
|
82
82
|
} from '../atoms/ToolbarPreset';
|
|
83
83
|
|
|
84
84
|
import {whiteboardContext} from './whiteboard/WhiteboardConfigure';
|
|
85
|
-
import {RoomPhase} from 'white-web-sdk';
|
|
85
|
+
// import {RoomPhase} from 'white-web-sdk';
|
|
86
|
+
// Commented out for fastboard migration
|
|
87
|
+
enum RoomPhase {
|
|
88
|
+
Connecting = 'connecting',
|
|
89
|
+
Connected = 'connected',
|
|
90
|
+
Reconnecting = 'reconnecting',
|
|
91
|
+
Disconnecting = 'disconnecting',
|
|
92
|
+
Disconnected = 'disconnected',
|
|
93
|
+
}
|
|
86
94
|
import {useNoiseSupression} from '../app-state/useNoiseSupression';
|
|
87
95
|
|
|
88
96
|
import {useVB} from './virtual-background/useVB';
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/*
|
|
2
|
+
********************************************
|
|
3
|
+
Copyright © 2021 Agora Lab, Inc., all rights reserved.
|
|
4
|
+
AppBuilder and all associated components, source code, APIs, services, and documentation
|
|
5
|
+
(the "Materials") are owned by Agora Lab, Inc. and its licensors. The Materials may not be
|
|
6
|
+
accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
|
|
7
|
+
Use without a license or in violation of any license terms and conditions (including use for
|
|
8
|
+
any purpose competitive to Agora Lab, Inc.'s business) is strictly prohibited. For more
|
|
9
|
+
information visit https://appbuilder.agora.io.
|
|
10
|
+
*********************************************
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import React, {useRef, useEffect} from 'react';
|
|
14
|
+
import {StyleSheet, View, Text} from 'react-native';
|
|
15
|
+
import {useRoomInfo} from 'customization-api';
|
|
16
|
+
import {useString} from '../../utils/useString';
|
|
17
|
+
import {whiteboardInitializingText} from '../../language/default-labels/videoCallScreenLabels';
|
|
18
|
+
import {useFastboard, Fastboard, createFastboard, FastboardApp} from '@netless/fastboard-react/full';
|
|
19
|
+
|
|
20
|
+
import {useLocalUid} from '../../../agora-rn-uikit';
|
|
21
|
+
import useUserName from '../../utils/useUserName';
|
|
22
|
+
|
|
23
|
+
interface FastBoardViewProps {
|
|
24
|
+
showToolbox?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Technical Note: Why we are not using the 'useFastboard' hook?
|
|
29
|
+
*
|
|
30
|
+
* We replaced the standard 'useFastboard' hook with a manual 'FastboardManager' implementation
|
|
31
|
+
* to solve a critical race condition in React 18+ Strict Mode.
|
|
32
|
+
*
|
|
33
|
+
* Issue: "[WindowManager]: Already created cannot be created again"
|
|
34
|
+
*
|
|
35
|
+
* In Strict Mode, React intentionally mounts, unmounts, and remounts components rapidly
|
|
36
|
+
* to detect side-effects. The standard hook attempts to initialize the Fastboard singleton
|
|
37
|
+
* twice in parallel. The first initialization is still "pending" when the second one starts,
|
|
38
|
+
* causing the underlying WindowManager to crash because it doesn't support concurrent init calls.
|
|
39
|
+
*
|
|
40
|
+
* Solution: The 'FastboardManager' below uses Reference Counting and Singleton pattern to:
|
|
41
|
+
* 1. Deduplicate initialization requests (reusing the same Promise).
|
|
42
|
+
* 2. Delay cleanup slightly to handle the rapid Unmount -> Mount cycle without destroying the instance.
|
|
43
|
+
*/
|
|
44
|
+
const FastBoardView: React.FC<FastBoardViewProps> = ({showToolbox = true}) => {
|
|
45
|
+
const {
|
|
46
|
+
data: {whiteboard: {room_token, room_uuid} = {}, isHost},
|
|
47
|
+
} = useRoomInfo();
|
|
48
|
+
|
|
49
|
+
const localUid = useLocalUid();
|
|
50
|
+
const [name] = useUserName();
|
|
51
|
+
|
|
52
|
+
const whiteboardInitializing = useString(whiteboardInitializingText)();
|
|
53
|
+
|
|
54
|
+
// Generate stable UID - only once
|
|
55
|
+
// Use local user's name or fallback to UID if name is not available
|
|
56
|
+
const uidRef = useRef<string>(name || String(localUid));
|
|
57
|
+
const [fastboard, setFastboard] = React.useState<FastboardApp | null>(null);
|
|
58
|
+
|
|
59
|
+
// Configuration object - Memoize stringified version to detect changes
|
|
60
|
+
const config = React.useMemo(() => ({
|
|
61
|
+
sdkConfig: {
|
|
62
|
+
appIdentifier: 'EEJBQPVbEe2Bao8ZShuoHQ/hgB5eo0qcDbVig',
|
|
63
|
+
region: 'us-sv',
|
|
64
|
+
},
|
|
65
|
+
joinRoom: {
|
|
66
|
+
uid: uidRef.current,
|
|
67
|
+
uuid: room_uuid,
|
|
68
|
+
roomToken: room_token,
|
|
69
|
+
},
|
|
70
|
+
}), [room_uuid, room_token]);
|
|
71
|
+
|
|
72
|
+
const configStr = JSON.stringify(config);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
let isMounted = true;
|
|
76
|
+
|
|
77
|
+
const initFastboard = async () => {
|
|
78
|
+
try {
|
|
79
|
+
const app = await FastboardManager.acquire(configStr, config);
|
|
80
|
+
if (isMounted) {
|
|
81
|
+
setFastboard(app);
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error("Fastboard initialization failed:", error);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
initFastboard();
|
|
89
|
+
|
|
90
|
+
return () => {
|
|
91
|
+
isMounted = false;
|
|
92
|
+
FastboardManager.release(configStr);
|
|
93
|
+
};
|
|
94
|
+
}, [configStr, config]);
|
|
95
|
+
|
|
96
|
+
// Show loading if fastboard not ready yet
|
|
97
|
+
if (!fastboard) {
|
|
98
|
+
return (
|
|
99
|
+
<View style={styles.container}>
|
|
100
|
+
<View style={styles.placeholder}>
|
|
101
|
+
<Text style={styles.placeholderText}>{whiteboardInitializing}</Text>
|
|
102
|
+
</View>
|
|
103
|
+
</View>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<View style={styles.container}>
|
|
109
|
+
<div style={divStyles.fastboardContainer}>
|
|
110
|
+
<Fastboard app={fastboard} />
|
|
111
|
+
</div>
|
|
112
|
+
</View>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Global Manager to handle Strict Mode and Singleton constraints
|
|
117
|
+
const FastboardManager = {
|
|
118
|
+
activeConfig: null as string | null,
|
|
119
|
+
instance: null as FastboardApp | null,
|
|
120
|
+
promise: null as Promise<FastboardApp> | null,
|
|
121
|
+
subscribers: 0,
|
|
122
|
+
|
|
123
|
+
acquire: async (configStr: string, config: any): Promise<FastboardApp> => {
|
|
124
|
+
FastboardManager.subscribers++;
|
|
125
|
+
|
|
126
|
+
// If config matches and we have an instance/promise, reuse it
|
|
127
|
+
if (FastboardManager.activeConfig === configStr) {
|
|
128
|
+
if (FastboardManager.instance) return FastboardManager.instance;
|
|
129
|
+
if (FastboardManager.promise) return FastboardManager.promise;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Config mismatch! We must cleanup the previous board before creating a new one.
|
|
133
|
+
// This happens if component remounts with new UID (e.g. Pin to Top).
|
|
134
|
+
|
|
135
|
+
// 1. If there's a pending loading operation, wait for it and destroy the result.
|
|
136
|
+
if (FastboardManager.promise) {
|
|
137
|
+
try {
|
|
138
|
+
const oldApp = await FastboardManager.promise;
|
|
139
|
+
// Double check if it wasn't already destroyed or reassigned
|
|
140
|
+
if (oldApp) oldApp.destroy();
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.warn("Error cleaning up previous pending Fastboard:", e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 2. If there's an active instance, destroy it.
|
|
147
|
+
if (FastboardManager.instance) {
|
|
148
|
+
try {
|
|
149
|
+
FastboardManager.instance.destroy();
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.warn("Error cleaning up previous active Fastboard:", e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Reset state
|
|
156
|
+
FastboardManager.instance = null;
|
|
157
|
+
FastboardManager.promise = null;
|
|
158
|
+
FastboardManager.activeConfig = configStr;
|
|
159
|
+
|
|
160
|
+
// 3. Create new instance
|
|
161
|
+
FastboardManager.promise = createFastboard(config).then(app => {
|
|
162
|
+
// Check if we are still the active config
|
|
163
|
+
if (FastboardManager.activeConfig === configStr) {
|
|
164
|
+
FastboardManager.instance = app;
|
|
165
|
+
return app;
|
|
166
|
+
} else {
|
|
167
|
+
// Config changed while loading
|
|
168
|
+
app.destroy();
|
|
169
|
+
throw new Error("Fastboard config changed during initialization");
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return FastboardManager.promise;
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
release: (configStr: string) => {
|
|
177
|
+
FastboardManager.subscribers--;
|
|
178
|
+
|
|
179
|
+
// Delayed cleanup to handle Strict Mode "Unmount -> Mount" flicker
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
if (FastboardManager.subscribers === 0 && FastboardManager.activeConfig === configStr) {
|
|
182
|
+
if (FastboardManager.instance) {
|
|
183
|
+
FastboardManager.instance.destroy();
|
|
184
|
+
FastboardManager.instance = null;
|
|
185
|
+
}
|
|
186
|
+
FastboardManager.promise = null;
|
|
187
|
+
FastboardManager.activeConfig = null;
|
|
188
|
+
}
|
|
189
|
+
}, 200);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const styles = StyleSheet.create({
|
|
194
|
+
container: {
|
|
195
|
+
flex: 1,
|
|
196
|
+
position: 'relative',
|
|
197
|
+
backgroundColor: '#ffffff',
|
|
198
|
+
},
|
|
199
|
+
placeholder: {
|
|
200
|
+
position: 'absolute',
|
|
201
|
+
width: '100%',
|
|
202
|
+
height: '100%',
|
|
203
|
+
backgroundColor: '#f5f5f5',
|
|
204
|
+
display: 'flex',
|
|
205
|
+
justifyContent: 'center',
|
|
206
|
+
alignItems: 'center',
|
|
207
|
+
},
|
|
208
|
+
placeholderText: {
|
|
209
|
+
color: '#666666',
|
|
210
|
+
fontSize: 16,
|
|
211
|
+
},
|
|
212
|
+
errorText: {
|
|
213
|
+
color: '#ff4444',
|
|
214
|
+
fontSize: 16,
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const divStyles = {
|
|
219
|
+
fastboardContainer: {
|
|
220
|
+
width: '100%',
|
|
221
|
+
height: '100%',
|
|
222
|
+
borderRadius: 4,
|
|
223
|
+
overflow: 'hidden' as const,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export default FastBoardView;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
//import './StrokeWidthTool.less';
|
|
3
|
-
import {Color, Room, RoomState} from 'white-web-sdk';
|
|
3
|
+
// import {Color, Room, RoomState} from 'white-web-sdk';
|
|
4
|
+
// Commented out for fastboard migration
|
|
5
|
+
type Color = [number, number, number];
|
|
6
|
+
type Room = any;
|
|
7
|
+
type RoomState = any;
|
|
4
8
|
import {View, Text} from 'react-native';
|
|
5
9
|
import ThemeConfig from '../../theme';
|
|
6
10
|
import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
|
|
@@ -7,7 +7,15 @@ import {
|
|
|
7
7
|
useRoomInfo,
|
|
8
8
|
} from 'customization-api';
|
|
9
9
|
import {whiteboardContext} from './WhiteboardConfigure';
|
|
10
|
-
import {RoomPhase} from 'white-web-sdk';
|
|
10
|
+
// import {RoomPhase} from 'white-web-sdk';
|
|
11
|
+
// Commented out for fastboard migration
|
|
12
|
+
enum RoomPhase {
|
|
13
|
+
Connecting = 'connecting',
|
|
14
|
+
Connected = 'connected',
|
|
15
|
+
Reconnecting = 'reconnecting',
|
|
16
|
+
Disconnecting = 'disconnecting',
|
|
17
|
+
Disconnected = 'disconnected',
|
|
18
|
+
}
|
|
11
19
|
import IconButton from '../../atoms/IconButton';
|
|
12
20
|
import {EventNames} from '../../rtm-events';
|
|
13
21
|
|
|
@@ -17,7 +17,15 @@ import {
|
|
|
17
17
|
whiteboardPaper,
|
|
18
18
|
} from './WhiteboardConfigure';
|
|
19
19
|
import {StyleSheet, View, Text} from 'react-native';
|
|
20
|
-
import {RoomPhase, ApplianceNames} from 'white-web-sdk';
|
|
20
|
+
// import {RoomPhase, ApplianceNames} from 'white-web-sdk';
|
|
21
|
+
// Commented out for fastboard migration
|
|
22
|
+
enum RoomPhase {
|
|
23
|
+
Connecting = 'connecting',
|
|
24
|
+
Connected = 'connected',
|
|
25
|
+
Reconnecting = 'reconnecting',
|
|
26
|
+
Disconnecting = 'disconnecting',
|
|
27
|
+
Disconnected = 'disconnected',
|
|
28
|
+
}
|
|
21
29
|
import WhiteboardToolBox from './WhiteboardToolBox';
|
|
22
30
|
import WhiteboardWidget from './WhiteboardWidget';
|
|
23
31
|
|
|
@@ -8,11 +8,22 @@ import {
|
|
|
8
8
|
randomIntFromInterval,
|
|
9
9
|
randomString,
|
|
10
10
|
} from '../../utils/common';
|
|
11
|
-
import {WhiteWebSdk, RoomPhase, Room, ViewMode} from 'white-web-sdk';
|
|
11
|
+
// import {WhiteWebSdk, RoomPhase, Room, ViewMode} from 'white-web-sdk';
|
|
12
|
+
// Commented out for fastboard migration - types defined locally
|
|
13
|
+
type Room = any;
|
|
14
|
+
type ViewMode = any;
|
|
15
|
+
type WhiteWebSdk = any;
|
|
16
|
+
enum RoomPhase {
|
|
17
|
+
Connecting = 'connecting',
|
|
18
|
+
Connected = 'connected',
|
|
19
|
+
Reconnecting = 'reconnecting',
|
|
20
|
+
Disconnecting = 'disconnecting',
|
|
21
|
+
Disconnected = 'disconnected',
|
|
22
|
+
}
|
|
12
23
|
import LocalEventEmitter, {
|
|
13
24
|
LocalEventsEnum,
|
|
14
25
|
} from '../../rtm-events-api/LocalEvents';
|
|
15
|
-
import {CursorTool} from './WhiteboardCursor';
|
|
26
|
+
// import {CursorTool} from './WhiteboardCursor'; // Disabled for fastboard migration
|
|
16
27
|
import useUserName from '../../utils/useUserName';
|
|
17
28
|
import {DefaultLayouts} from '../../pages/video-call/DefaultLayouts';
|
|
18
29
|
import events, {PersistanceLevel} from '../../rtm-events-api';
|
|
@@ -117,23 +128,24 @@ const WhiteboardConfigure: React.FC<WhiteboardPropsInterface> = props => {
|
|
|
117
128
|
const whiteboardRoom = useRef({} as Room);
|
|
118
129
|
const {pinnedUid, activeUids} = useContent();
|
|
119
130
|
const prevImageUploadHeightRef = useRef(0);
|
|
120
|
-
const cursorAdapter = new CursorTool();
|
|
131
|
+
// const cursorAdapter = new CursorTool(); // Disabled for fastboard migration
|
|
121
132
|
const uploadPendingRef = useRef(false);
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
134
|
+
// Disabled for fastboard migration - FastBoardView handles camera
|
|
135
|
+
// useEffect(() => {
|
|
136
|
+
// if (
|
|
137
|
+
// whiteboardRoomState === RoomPhase.Connected &&
|
|
138
|
+
// pinnedUid &&
|
|
139
|
+
// pinnedUid == whiteboardUidRef.current
|
|
140
|
+
// ) {
|
|
141
|
+
// whiteboardRoom?.current?.moveCamera &&
|
|
142
|
+
// whiteboardRoom?.current?.moveCamera({
|
|
143
|
+
// centerX: 0,
|
|
144
|
+
// centerY: 0,
|
|
145
|
+
// scale: 1,
|
|
146
|
+
// });
|
|
147
|
+
// }
|
|
148
|
+
// }, [pinnedUid, whiteboardRoomState]);
|
|
137
149
|
|
|
138
150
|
const [name] = useUserName();
|
|
139
151
|
const {
|
|
@@ -143,34 +155,35 @@ const WhiteboardConfigure: React.FC<WhiteboardPropsInterface> = props => {
|
|
|
143
155
|
} = useRoomInfo();
|
|
144
156
|
const {currentLayout} = useLayout();
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
158
|
+
// Disabled for fastboard migration - FastBoardView handles writable state
|
|
159
|
+
// useEffect(() => {
|
|
160
|
+
// try {
|
|
161
|
+
// if (
|
|
162
|
+
// whiteboardRoomState === RoomPhase.Connected &&
|
|
163
|
+
// isHost &&
|
|
164
|
+
// !isMobileUA()
|
|
165
|
+
// ) {
|
|
166
|
+
// if (
|
|
167
|
+
// currentLayout === DefaultLayouts[1].name &&
|
|
168
|
+
// activeUids &&
|
|
169
|
+
// activeUids?.length &&
|
|
170
|
+
// (activeUids[0] === getWhiteboardUid() ||
|
|
171
|
+
// pinnedUid === getWhiteboardUid())
|
|
172
|
+
// ) {
|
|
173
|
+
// whiteboardRoom?.current?.setWritable(true);
|
|
174
|
+
// } else {
|
|
175
|
+
// whiteboardRoom?.current?.setWritable(false);
|
|
176
|
+
// }
|
|
177
|
+
// }
|
|
178
|
+
// } catch (error) {
|
|
179
|
+
// logger.error(
|
|
180
|
+
// LogSource.Internals,
|
|
181
|
+
// 'WHITEBOARD',
|
|
182
|
+
// 'error on whiteboard setWritable',
|
|
183
|
+
// error,
|
|
184
|
+
// );
|
|
185
|
+
// }
|
|
186
|
+
// }, [currentLayout, isHost, whiteboardRoomState, activeUids, pinnedUid]);
|
|
174
187
|
|
|
175
188
|
const BoardColorChangedCallBack = ({boardColor}) => {
|
|
176
189
|
setBoardColor(boardColor);
|
|
@@ -213,94 +226,20 @@ const WhiteboardConfigure: React.FC<WhiteboardPropsInterface> = props => {
|
|
|
213
226
|
};
|
|
214
227
|
}, []);
|
|
215
228
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
let count = 0;
|
|
221
|
-
let focus = {
|
|
222
|
-
x: 0,
|
|
223
|
-
y: 0,
|
|
224
|
-
};
|
|
225
|
-
for (const key in images) {
|
|
226
|
-
if (Object.prototype.hasOwnProperty.call(images, key)) {
|
|
227
|
-
const element = images[key];
|
|
228
|
-
const uuid = key + ' ' + randomString();
|
|
229
|
-
const x = 0 + prevImageWidth + 50;
|
|
230
|
-
const y = 0 + prevImageUploadHeightRef?.current + 50;
|
|
231
|
-
whiteboardRoom.current?.insertImage({
|
|
232
|
-
centerX: x,
|
|
233
|
-
centerY: y,
|
|
234
|
-
height: dummyHeight,
|
|
235
|
-
width: dummyWidth,
|
|
236
|
-
uuid: uuid,
|
|
237
|
-
locked: false,
|
|
238
|
-
});
|
|
239
|
-
if (count === 0) {
|
|
240
|
-
focus.x = x;
|
|
241
|
-
focus.y = y;
|
|
242
|
-
}
|
|
243
|
-
setTimeout(() => {
|
|
244
|
-
whiteboardRoom.current?.completeImageUpload(uuid, element.url);
|
|
245
|
-
}, 1000);
|
|
246
|
-
prevImageWidth = prevImageWidth + 50 + dummyWidth;
|
|
247
|
-
if ((count + 1) % 4 === 0) {
|
|
248
|
-
prevImageUploadHeightRef.current =
|
|
249
|
-
prevImageUploadHeightRef.current + 50 + dummyHeight;
|
|
250
|
-
prevImageWidth = 0;
|
|
251
|
-
} else {
|
|
252
|
-
prevImageHeight = dummyHeight;
|
|
253
|
-
}
|
|
254
|
-
count = count + 1;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
//for next image upload
|
|
259
|
-
if ((count + 1) % 4 !== 0) {
|
|
260
|
-
prevImageUploadHeightRef.current =
|
|
261
|
-
prevImageUploadHeightRef.current + 50 + prevImageHeight;
|
|
262
|
-
}
|
|
263
|
-
uploadPendingRef.current = false;
|
|
264
|
-
|
|
265
|
-
//focus the uploaded doc/image
|
|
266
|
-
whiteboardRoom.current?.moveCamera({
|
|
267
|
-
centerX: focus.x,
|
|
268
|
-
centerY: focus.y,
|
|
269
|
-
});
|
|
270
|
-
sendLastImageUploadPositionToRemoteUsers(
|
|
271
|
-
prevImageUploadHeightRef.current,
|
|
272
|
-
);
|
|
273
|
-
}
|
|
229
|
+
// Disabled for fastboard migration - file upload not supported yet
|
|
230
|
+
const fileUploadCallBack = (images: any) => {
|
|
231
|
+
// TODO: Implement file upload for fastboard if needed
|
|
232
|
+
console.log('File upload not yet implemented for fastboard');
|
|
274
233
|
};
|
|
275
234
|
|
|
276
235
|
const setUploadRef = () => {
|
|
277
236
|
uploadPendingRef.current = true;
|
|
278
237
|
};
|
|
279
238
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const uuid = randomString();
|
|
285
|
-
const y = 0 + prevImageUploadHeightRef?.current + 50;
|
|
286
|
-
whiteboardRoom.current?.insertImage({
|
|
287
|
-
centerX: 0,
|
|
288
|
-
centerY: y,
|
|
289
|
-
height: 300,
|
|
290
|
-
width: 300,
|
|
291
|
-
uuid: uuid,
|
|
292
|
-
locked: false,
|
|
293
|
-
});
|
|
294
|
-
setTimeout(() => {
|
|
295
|
-
whiteboardRoom.current?.completeImageUpload(uuid, url);
|
|
296
|
-
}, 1000);
|
|
297
|
-
whiteboardRoom.current?.moveCamera({
|
|
298
|
-
centerX: 0,
|
|
299
|
-
centerY: y,
|
|
300
|
-
});
|
|
301
|
-
prevImageUploadHeightRef.current =
|
|
302
|
-
prevImageUploadHeightRef.current + 50 + 300 + 100;
|
|
303
|
-
sendLastImageUploadPositionToRemoteUsers(prevImageUploadHeightRef.current);
|
|
239
|
+
// Disabled for fastboard migration - image insert not supported yet
|
|
240
|
+
const insertImageIntoWhiteboard = (url: string) => {
|
|
241
|
+
// TODO: Implement image insert for fastboard if needed
|
|
242
|
+
console.log('Image insert not yet implemented for fastboard');
|
|
304
243
|
};
|
|
305
244
|
|
|
306
245
|
const sendLastImageUploadPositionToRemoteUsers = (height: number) => {
|
|
@@ -326,79 +265,9 @@ const WhiteboardConfigure: React.FC<WhiteboardPropsInterface> = props => {
|
|
|
326
265
|
};
|
|
327
266
|
}, []);
|
|
328
267
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const index = randomIntFromInterval(0, 9);
|
|
333
|
-
setWhiteboardRoomState(RoomPhase.Connecting);
|
|
334
|
-
logger.log(LogSource.Internals, 'WHITEBOARD', 'Trying to join room');
|
|
335
|
-
whiteWebSdkClient.current
|
|
336
|
-
.joinRoom({
|
|
337
|
-
cursorAdapter: cursorAdapter,
|
|
338
|
-
uid: `${whiteboardUidRef.current}`,
|
|
339
|
-
uuid: room_uuid,
|
|
340
|
-
roomToken: room_token,
|
|
341
|
-
floatBar: true,
|
|
342
|
-
isWritable: isHost && !isMobileUA(),
|
|
343
|
-
userPayload: {
|
|
344
|
-
cursorName: name,
|
|
345
|
-
cursorColor: CursorColor[index].cursorColor,
|
|
346
|
-
textColor: CursorColor[index].textColor,
|
|
347
|
-
},
|
|
348
|
-
})
|
|
349
|
-
.then(room => {
|
|
350
|
-
logger.log(LogSource.Internals, 'WHITEBOARD', 'Join room successful');
|
|
351
|
-
whiteboardRoom.current = room;
|
|
352
|
-
cursorAdapter.setRoom(room);
|
|
353
|
-
whiteboardRoom.current?.setViewMode(ViewMode.Freedom);
|
|
354
|
-
whiteboardRoom.current?.bindHtmlElement(whiteboardPaper);
|
|
355
|
-
if (isHost && !isMobileUA()) {
|
|
356
|
-
whiteboardRoom.current?.setMemberState({
|
|
357
|
-
strokeColor: [0, 0, 0],
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
setWhiteboardRoomState(RoomPhase.Connected);
|
|
361
|
-
})
|
|
362
|
-
.catch(err => {
|
|
363
|
-
setWhiteboardRoomState(InitState);
|
|
364
|
-
logger.error(
|
|
365
|
-
LogSource.Internals,
|
|
366
|
-
'WHITEBOARD',
|
|
367
|
-
'Join room error',
|
|
368
|
-
err,
|
|
369
|
-
);
|
|
370
|
-
});
|
|
371
|
-
} catch (err) {
|
|
372
|
-
setWhiteboardRoomState(InitState);
|
|
373
|
-
logger.error(LogSource.Internals, 'WHITEBOARD', 'Join room error', err);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
const leave = () => {
|
|
378
|
-
const InitState = whiteboardRoomState;
|
|
379
|
-
try {
|
|
380
|
-
setWhiteboardRoomState(RoomPhase.Disconnecting);
|
|
381
|
-
whiteboardRoom.current
|
|
382
|
-
?.disconnect()
|
|
383
|
-
.then(() => {
|
|
384
|
-
whiteboardUidRef.current = Date.now();
|
|
385
|
-
whiteboardRoom.current?.bindHtmlElement(null);
|
|
386
|
-
setWhiteboardRoomState(RoomPhase.Disconnected);
|
|
387
|
-
})
|
|
388
|
-
.catch(err => {
|
|
389
|
-
setWhiteboardRoomState(InitState);
|
|
390
|
-
logger.error(
|
|
391
|
-
LogSource.Internals,
|
|
392
|
-
'WHITEBOARD',
|
|
393
|
-
'leave room error',
|
|
394
|
-
err,
|
|
395
|
-
);
|
|
396
|
-
});
|
|
397
|
-
} catch (err) {
|
|
398
|
-
setWhiteboardRoomState(InitState);
|
|
399
|
-
logger.error(LogSource.Internals, 'WHITEBOARD', 'leave room error', err);
|
|
400
|
-
}
|
|
401
|
-
};
|
|
268
|
+
// Disabled for fastboard migration - FastBoardView handles join/leave
|
|
269
|
+
// const join = () => { ... };
|
|
270
|
+
// const leave = () => { ... };
|
|
402
271
|
|
|
403
272
|
const joinWhiteboardRoom = () => {
|
|
404
273
|
setWhiteboardActive(true);
|
|
@@ -408,24 +277,35 @@ const WhiteboardConfigure: React.FC<WhiteboardPropsInterface> = props => {
|
|
|
408
277
|
setWhiteboardActive(false);
|
|
409
278
|
};
|
|
410
279
|
|
|
280
|
+
// Disabled for fastboard migration - FastBoardView handles its own connection
|
|
281
|
+
// useEffect(() => {
|
|
282
|
+
// if (!whiteWebSdkClient.current.joinRoom && whiteboardActive) {
|
|
283
|
+
// const appIdentifier = $config.WHITEBOARD_APPIDENTIFIER;
|
|
284
|
+
// whiteWebSdkClient.current = new WhiteWebSdk({
|
|
285
|
+
// appIdentifier: appIdentifier,
|
|
286
|
+
// region: $config.WHITEBOARD_REGION,
|
|
287
|
+
// });
|
|
288
|
+
// join();
|
|
289
|
+
// setWhiteboardStartedFirst(true);
|
|
290
|
+
// } else if (whiteboardActive) {
|
|
291
|
+
// join();
|
|
292
|
+
// } else {
|
|
293
|
+
// if (
|
|
294
|
+
// whiteboardRoom.current &&
|
|
295
|
+
// Object.keys(whiteboardRoom.current)?.length
|
|
296
|
+
// ) {
|
|
297
|
+
// leave();
|
|
298
|
+
// }
|
|
299
|
+
// }
|
|
300
|
+
// }, [whiteboardActive]);
|
|
301
|
+
|
|
302
|
+
// For fastboard: just set whiteboardStartedFirst when active
|
|
411
303
|
useEffect(() => {
|
|
412
|
-
if (
|
|
413
|
-
const appIdentifier = $config.WHITEBOARD_APPIDENTIFIER;
|
|
414
|
-
whiteWebSdkClient.current = new WhiteWebSdk({
|
|
415
|
-
appIdentifier: appIdentifier,
|
|
416
|
-
region: $config.WHITEBOARD_REGION,
|
|
417
|
-
});
|
|
418
|
-
join();
|
|
304
|
+
if (whiteboardActive) {
|
|
419
305
|
setWhiteboardStartedFirst(true);
|
|
420
|
-
|
|
421
|
-
join();
|
|
306
|
+
setWhiteboardRoomState(RoomPhase.Connected);
|
|
422
307
|
} else {
|
|
423
|
-
|
|
424
|
-
whiteboardRoom.current &&
|
|
425
|
-
Object.keys(whiteboardRoom.current)?.length
|
|
426
|
-
) {
|
|
427
|
-
leave();
|
|
428
|
-
}
|
|
308
|
+
setWhiteboardRoomState(RoomPhase.Disconnected);
|
|
429
309
|
}
|
|
430
310
|
}, [whiteboardActive]);
|
|
431
311
|
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from 'white-web-sdk';
|
|
2
|
+
// import {
|
|
3
|
+
// Cursor,
|
|
4
|
+
// CursorAdapter,
|
|
5
|
+
// CursorDescription,
|
|
6
|
+
// Player,
|
|
7
|
+
// Room,
|
|
8
|
+
// RoomMember,
|
|
9
|
+
// RoomState,
|
|
10
|
+
// } from 'white-web-sdk';
|
|
11
|
+
// Commented out for fastboard migration - types defined locally
|
|
12
|
+
type Cursor = any;
|
|
13
|
+
type CursorAdapter = any;
|
|
14
|
+
type CursorDescription = {x: number; y: number; width: number; height: number};
|
|
15
|
+
type Player = any;
|
|
16
|
+
type Room = any;
|
|
17
|
+
type RoomMember = any;
|
|
18
|
+
type RoomState = any;
|
|
11
19
|
|
|
12
20
|
export type CursorComponentProps = {
|
|
13
21
|
roomMember: RoomMember;
|
|
@@ -13,7 +13,21 @@
|
|
|
13
13
|
import React, {useContext, useEffect, useState} from 'react';
|
|
14
14
|
import {StyleSheet, View, Pressable} from 'react-native';
|
|
15
15
|
import {hexToRgb, isMobileUA, isWeb, randomString} from '../../utils/common';
|
|
16
|
-
import {ApplianceNames} from 'white-web-sdk';
|
|
16
|
+
// import {ApplianceNames} from 'white-web-sdk';
|
|
17
|
+
// Commented out for fastboard migration
|
|
18
|
+
const ApplianceNames = {
|
|
19
|
+
selector: 'selector',
|
|
20
|
+
pencil: 'pencil',
|
|
21
|
+
rectangle: 'rectangle',
|
|
22
|
+
ellipse: 'ellipse',
|
|
23
|
+
straight: 'straight',
|
|
24
|
+
arrow: 'arrow',
|
|
25
|
+
hand: 'hand',
|
|
26
|
+
laserPointer: 'laserPointer',
|
|
27
|
+
eraser: 'eraser',
|
|
28
|
+
text: 'text',
|
|
29
|
+
pencilEraser: 'pencilEraser',
|
|
30
|
+
} as const;
|
|
17
31
|
import StorageContext from '../../components/StorageContext';
|
|
18
32
|
import {useRoomInfo} from '../room-info/useRoomInfo';
|
|
19
33
|
import Toast from '../../../react-native-toast-message';
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
import React, {useRef, useEffect, useContext, useState} from 'react';
|
|
14
14
|
import {whiteboardContext} from './WhiteboardConfigure';
|
|
15
15
|
import {StyleSheet, View, Text} from 'react-native';
|
|
16
|
-
import {RoomPhase, ApplianceNames} from 'white-web-sdk';
|
|
16
|
+
// import {RoomPhase, ApplianceNames} from 'white-web-sdk';
|
|
17
|
+
// Commented out for fastboard migration
|
|
18
|
+
enum RoomPhase {
|
|
19
|
+
Connecting = 'connecting',
|
|
20
|
+
Connected = 'connected',
|
|
21
|
+
Reconnecting = 'reconnecting',
|
|
22
|
+
Disconnecting = 'disconnecting',
|
|
23
|
+
Disconnected = 'disconnected',
|
|
24
|
+
}
|
|
17
25
|
import WhiteboardToolBox from './WhiteboardToolBox';
|
|
18
26
|
import WhiteboardCanvas from './WhiteboardCanvas';
|
|
19
27
|
import {useContent, useLayout} from 'customization-api';
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
import React, {useContext, useState} from 'react';
|
|
14
14
|
import {StyleSheet, View, TouchableOpacity, Text} from 'react-native';
|
|
15
|
-
import {Room, RoomState} from 'white-web-sdk';
|
|
15
|
+
// import {Room, RoomState} from 'white-web-sdk';
|
|
16
|
+
// Commented out for fastboard migration
|
|
17
|
+
type Room = any;
|
|
18
|
+
type RoomState = any;
|
|
16
19
|
import {
|
|
17
20
|
IconButton,
|
|
18
21
|
useContent,
|
|
@@ -2,7 +2,8 @@ import React, {useContext} from 'react';
|
|
|
2
2
|
import {whiteboardContext} from './WhiteboardConfigure';
|
|
3
3
|
import VideoRenderer from '../../pages/video-call/VideoRenderer';
|
|
4
4
|
import {useContent} from 'customization-api';
|
|
5
|
-
import WhiteboardView from './WhiteboardView';
|
|
5
|
+
// import WhiteboardView from './WhiteboardView';
|
|
6
|
+
import FastBoardView from './FastBoardView';
|
|
6
7
|
|
|
7
8
|
const WhiteboardWrapper = () => {
|
|
8
9
|
const {getWhiteboardUid} = useContext(whiteboardContext);
|
|
@@ -28,7 +29,7 @@ const WhiteboardWrapper = () => {
|
|
|
28
29
|
name: 'Whiteboard',
|
|
29
30
|
muted: undefined,
|
|
30
31
|
}}
|
|
31
|
-
CustomChild={
|
|
32
|
+
CustomChild={FastBoardView}
|
|
32
33
|
/>
|
|
33
34
|
);
|
|
34
35
|
}
|