@meshagent/meshagent-react 0.38.1 → 0.38.3
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/CHANGELOG.md +17 -1
- package/README.md +78 -41
- package/dist/cjs/client-toolkits.d.ts +2 -2
- package/dist/cjs/client-toolkits.js +143 -10
- package/dist/cjs/document-connection-scope.d.ts +7 -12
- package/dist/cjs/document-connection-scope.js +88 -82
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/livekit-client.d.ts +23 -0
- package/dist/cjs/livekit-client.js +66 -0
- package/dist/cjs/livekit-protocol.d.ts +21 -0
- package/dist/cjs/livekit-protocol.js +97 -0
- package/dist/cjs/room-connection-scope.d.ts +16 -16
- package/dist/cjs/room-connection-scope.js +207 -90
- package/dist/cjs/room-participants.d.ts +2 -0
- package/dist/cjs/room-participants.js +46 -0
- package/dist/esm/client-toolkits.d.ts +2 -2
- package/dist/esm/client-toolkits.js +145 -12
- package/dist/esm/document-connection-scope.d.ts +7 -12
- package/dist/esm/document-connection-scope.js +88 -81
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +3 -2
- package/dist/esm/livekit-client.d.ts +23 -0
- package/dist/esm/livekit-client.js +61 -0
- package/dist/esm/livekit-protocol.d.ts +21 -0
- package/dist/esm/livekit-protocol.js +60 -0
- package/dist/esm/room-connection-scope.d.ts +16 -16
- package/dist/esm/room-connection-scope.js +205 -89
- package/dist/esm/room-participants.d.ts +2 -0
- package/dist/esm/room-participants.js +43 -0
- package/package.json +2 -2
- package/dist/cjs/chat.d.ts +0 -33
- package/dist/cjs/chat.js +0 -207
- package/dist/cjs/file-upload.d.ts +0 -43
- package/dist/cjs/file-upload.js +0 -168
- package/dist/esm/chat.d.ts +0 -33
- package/dist/esm/chat.js +0 -201
- package/dist/esm/file-upload.d.ts +0 -43
- package/dist/esm/file-upload.js +0 -163
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LivekitClient = exports.LivekitConnectionInfo = void 0;
|
|
4
|
+
const meshagent_1 = require("@meshagent/meshagent");
|
|
5
|
+
class LivekitConnectionInfo {
|
|
6
|
+
constructor({ url, token }) {
|
|
7
|
+
Object.defineProperty(this, "url", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: void 0
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(this, "token", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: void 0
|
|
18
|
+
});
|
|
19
|
+
this.url = url;
|
|
20
|
+
this.token = token;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.LivekitConnectionInfo = LivekitConnectionInfo;
|
|
24
|
+
class LivekitClient {
|
|
25
|
+
constructor({ room }) {
|
|
26
|
+
Object.defineProperty(this, "room", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
this.room = room;
|
|
33
|
+
}
|
|
34
|
+
async getConnectionInfo({ breakoutRoom, } = {}) {
|
|
35
|
+
const response = await this.room.invoke({
|
|
36
|
+
toolkit: 'livekit',
|
|
37
|
+
tool: 'connect',
|
|
38
|
+
input: { breakout_room: breakoutRoom ?? null },
|
|
39
|
+
});
|
|
40
|
+
if (!(response instanceof meshagent_1.JsonContent)) {
|
|
41
|
+
throw new meshagent_1.RoomServerException('unexpected return type from livekit.connect');
|
|
42
|
+
}
|
|
43
|
+
const responseJson = response.json;
|
|
44
|
+
if (typeof responseJson !== 'object'
|
|
45
|
+
|| responseJson == null
|
|
46
|
+
|| Array.isArray(responseJson)) {
|
|
47
|
+
throw new meshagent_1.RoomServerException('unexpected return type from livekit.connect');
|
|
48
|
+
}
|
|
49
|
+
const token = responseJson.token;
|
|
50
|
+
const url = responseJson.url;
|
|
51
|
+
if (typeof token !== 'string' || typeof url !== 'string') {
|
|
52
|
+
throw new meshagent_1.RoomServerException('unexpected return type from livekit.connect');
|
|
53
|
+
}
|
|
54
|
+
return new LivekitConnectionInfo({ token, url });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.LivekitClient = LivekitClient;
|
|
58
|
+
if (!Object.getOwnPropertyDescriptor(meshagent_1.RoomClient.prototype, 'livekit')) {
|
|
59
|
+
Object.defineProperty(meshagent_1.RoomClient.prototype, 'livekit', {
|
|
60
|
+
configurable: true,
|
|
61
|
+
enumerable: false,
|
|
62
|
+
get() {
|
|
63
|
+
return new LivekitClient({ room: this });
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ProtocolChannel } from '@meshagent/meshagent';
|
|
2
|
+
import * as livekit from 'livekit-client';
|
|
3
|
+
export declare class LivekitProtocolChannel implements ProtocolChannel {
|
|
4
|
+
private readonly room;
|
|
5
|
+
private readonly remote;
|
|
6
|
+
private readonly topic;
|
|
7
|
+
private onDataReceived?;
|
|
8
|
+
private readonly handleDataReceivedBound;
|
|
9
|
+
constructor({ room, remote, topic, }: {
|
|
10
|
+
room: livekit.Room;
|
|
11
|
+
remote: livekit.RemoteParticipant;
|
|
12
|
+
topic: string;
|
|
13
|
+
});
|
|
14
|
+
start(onDataReceived: (data: Uint8Array) => void, _params: {
|
|
15
|
+
onDone?: () => void;
|
|
16
|
+
onError?: (error: unknown) => void;
|
|
17
|
+
}): void;
|
|
18
|
+
sendData(data: Uint8Array): Promise<void>;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
private handleDataReceived;
|
|
21
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LivekitProtocolChannel = void 0;
|
|
37
|
+
const livekit = __importStar(require("livekit-client"));
|
|
38
|
+
class LivekitProtocolChannel {
|
|
39
|
+
constructor({ room, remote, topic, }) {
|
|
40
|
+
Object.defineProperty(this, "room", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
writable: true,
|
|
44
|
+
value: void 0
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(this, "remote", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: void 0
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(this, "topic", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: void 0
|
|
57
|
+
});
|
|
58
|
+
Object.defineProperty(this, "onDataReceived", {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
writable: true,
|
|
62
|
+
value: void 0
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(this, "handleDataReceivedBound", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
configurable: true,
|
|
67
|
+
writable: true,
|
|
68
|
+
value: void 0
|
|
69
|
+
});
|
|
70
|
+
this.room = room;
|
|
71
|
+
this.remote = remote;
|
|
72
|
+
this.topic = topic;
|
|
73
|
+
this.handleDataReceivedBound = this.handleDataReceived.bind(this);
|
|
74
|
+
}
|
|
75
|
+
start(onDataReceived, _params) {
|
|
76
|
+
this.onDataReceived = onDataReceived;
|
|
77
|
+
this.room.on(livekit.RoomEvent.DataReceived, this.handleDataReceivedBound);
|
|
78
|
+
}
|
|
79
|
+
async sendData(data) {
|
|
80
|
+
await this.room.localParticipant.publishData(data, {
|
|
81
|
+
reliable: true,
|
|
82
|
+
topic: this.topic,
|
|
83
|
+
destinationIdentities: [this.remote.identity],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
dispose() {
|
|
87
|
+
this.room.off(livekit.RoomEvent.DataReceived, this.handleDataReceivedBound);
|
|
88
|
+
this.onDataReceived = undefined;
|
|
89
|
+
}
|
|
90
|
+
handleDataReceived(payload, participant, _kind, topic, _encryptionType) {
|
|
91
|
+
const identityMatches = participant?.identity === this.remote.identity;
|
|
92
|
+
if (identityMatches && topic === this.topic) {
|
|
93
|
+
this.onDataReceived?.(payload);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.LivekitProtocolChannel = LivekitProtocolChannel;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { RoomClient } from '@meshagent/meshagent';
|
|
2
|
-
|
|
3
|
-
url: string;
|
|
4
|
-
jwt: string;
|
|
5
|
-
}
|
|
1
|
+
import { type OAuthTokenRequest, RoomClient, type SecretRequest } from '@meshagent/meshagent';
|
|
2
|
+
import type { RoomConnectionInfo } from '@meshagent/meshagent';
|
|
6
3
|
export declare const developmentAuthorization: ({ url, projectId, apiKeyId, participantName, roomName, secret, }: {
|
|
7
4
|
url: string;
|
|
8
5
|
projectId: string;
|
|
@@ -11,27 +8,30 @@ export declare const developmentAuthorization: ({ url, projectId, apiKeyId, part
|
|
|
11
8
|
roomName: string;
|
|
12
9
|
secret: string;
|
|
13
10
|
}) => (() => Promise<RoomConnectionInfo>);
|
|
11
|
+
export declare const staticAuthorization: ({ projectId, roomName, url, jwt, }: {
|
|
12
|
+
projectId: string;
|
|
13
|
+
roomName: string;
|
|
14
|
+
url: string;
|
|
15
|
+
jwt: string;
|
|
16
|
+
}) => (() => Promise<RoomConnectionInfo>);
|
|
14
17
|
export interface UseRoomConnectionOptions {
|
|
15
|
-
|
|
16
|
-
authorization: () => Promise<
|
|
17
|
-
url: string;
|
|
18
|
-
jwt: string;
|
|
19
|
-
}>;
|
|
20
|
-
/** Enable the optional messaging layer (default = `true`). */
|
|
18
|
+
reconnectKey?: string;
|
|
19
|
+
authorization: () => Promise<RoomConnectionInfo>;
|
|
21
20
|
enableMessaging?: boolean;
|
|
21
|
+
onReady?: (room: RoomClient) => void;
|
|
22
|
+
oauthTokenRequestHandler?: (room: RoomClient, request: OAuthTokenRequest) => Promise<void> | void;
|
|
23
|
+
secretRequestHandler?: (room: RoomClient, request: SecretRequest) => Promise<void> | void;
|
|
24
|
+
roomClientFactory?: (connectionInfo: RoomConnectionInfo) => RoomClient;
|
|
22
25
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Shape of the object returned by the hook.
|
|
25
|
-
*/
|
|
26
26
|
export interface UseRoomConnectionResult {
|
|
27
27
|
client: RoomClient | null;
|
|
28
|
-
state: 'authorizing' | 'connecting' | 'ready' | 'done';
|
|
28
|
+
state: 'authorizing' | 'connecting' | 'retrying' | 'ready' | 'done';
|
|
29
29
|
ready: boolean;
|
|
30
30
|
done: boolean;
|
|
31
31
|
error: unknown;
|
|
32
32
|
dispose: () => void;
|
|
33
33
|
}
|
|
34
|
-
export declare function useRoomConnection(
|
|
34
|
+
export declare function useRoomConnection({ reconnectKey, authorization, enableMessaging, onReady, oauthTokenRequestHandler, secretRequestHandler, roomClientFactory, }: UseRoomConnectionOptions): UseRoomConnectionResult;
|
|
35
35
|
export interface UseRoomIndicatorsResult {
|
|
36
36
|
typing: boolean;
|
|
37
37
|
thinking: boolean;
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.developmentAuthorization = void 0;
|
|
3
|
+
exports.staticAuthorization = exports.developmentAuthorization = void 0;
|
|
4
4
|
exports.useRoomConnection = useRoomConnection;
|
|
5
5
|
exports.useRoomIndicators = useRoomIndicators;
|
|
6
6
|
const react_1 = require("react");
|
|
7
|
-
const subscribe_async_gen_1 = require("./subscribe-async-gen");
|
|
8
7
|
const meshagent_1 = require("@meshagent/meshagent");
|
|
9
|
-
const
|
|
8
|
+
const subscribe_async_gen_1 = require("./subscribe-async-gen");
|
|
9
|
+
const retryBaseDelayMs = 500;
|
|
10
|
+
const retryMaxDelayMs = 30000;
|
|
11
|
+
function getRetryDelayMs(retryCount) {
|
|
12
|
+
return Math.min(retryMaxDelayMs, retryBaseDelayMs * 2 ** retryCount);
|
|
13
|
+
}
|
|
14
|
+
function isRetryableConnectionError(error) {
|
|
15
|
+
return error instanceof meshagent_1.RoomServerException && error.retryable;
|
|
16
|
+
}
|
|
10
17
|
/* -------------------------------------------------
|
|
11
18
|
* Authorization helpers
|
|
12
19
|
* ------------------------------------------------- */
|
|
13
20
|
const developmentAuthorization = ({ url, projectId, apiKeyId, participantName, roomName, secret, }) => async () => {
|
|
14
|
-
const token = new
|
|
21
|
+
const token = new meshagent_1.ParticipantToken({
|
|
15
22
|
name: participantName,
|
|
16
23
|
projectId,
|
|
17
24
|
apiKeyId,
|
|
@@ -19,72 +26,171 @@ const developmentAuthorization = ({ url, projectId, apiKeyId, participantName, r
|
|
|
19
26
|
token.addRoomGrant(roomName);
|
|
20
27
|
token.addRoleGrant('user');
|
|
21
28
|
const jwt = await token.toJwt({ token: secret });
|
|
22
|
-
return {
|
|
29
|
+
return {
|
|
30
|
+
jwt,
|
|
31
|
+
projectId,
|
|
32
|
+
roomName,
|
|
33
|
+
roomUrl: url,
|
|
34
|
+
};
|
|
23
35
|
};
|
|
24
36
|
exports.developmentAuthorization = developmentAuthorization;
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
const staticAuthorization = ({ projectId, roomName, url, jwt, }) => async () => ({
|
|
38
|
+
jwt,
|
|
39
|
+
projectId,
|
|
40
|
+
roomName,
|
|
41
|
+
roomUrl: url,
|
|
42
|
+
});
|
|
43
|
+
exports.staticAuthorization = staticAuthorization;
|
|
44
|
+
function useRoomConnection({ reconnectKey, authorization, enableMessaging = true, onReady, oauthTokenRequestHandler, secretRequestHandler, roomClientFactory, }) {
|
|
27
45
|
const [client, setClient] = (0, react_1.useState)(null);
|
|
28
46
|
const [ready, setReady] = (0, react_1.useState)(false);
|
|
29
47
|
const [state, setState] = (0, react_1.useState)('authorizing');
|
|
30
48
|
const [error, setError] = (0, react_1.useState)(null);
|
|
31
|
-
// Keep the latest client in a ref so we can call `dispose` in cleanup.
|
|
32
49
|
const clientRef = (0, react_1.useRef)(null);
|
|
33
|
-
|
|
34
|
-
// Instance method exposed to consumers (rarely needed).
|
|
35
|
-
const dispose = () => {
|
|
36
|
-
clientRef.current?.dispose();
|
|
37
|
-
setState('done');
|
|
38
|
-
};
|
|
50
|
+
const cancelConnectionRef = (0, react_1.useRef)(() => { });
|
|
39
51
|
(0, react_1.useEffect)(() => {
|
|
40
52
|
let cancelled = false;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
let retryTimeout = null;
|
|
54
|
+
const clearRetryTimeout = () => {
|
|
55
|
+
if (retryTimeout != null) {
|
|
56
|
+
clearTimeout(retryTimeout);
|
|
57
|
+
retryTimeout = null;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const disposeClient = (room) => {
|
|
61
|
+
if (room == null) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (clientRef.current === room) {
|
|
65
|
+
clientRef.current = null;
|
|
66
|
+
}
|
|
67
|
+
room.dispose();
|
|
68
|
+
};
|
|
69
|
+
const waitForRetry = (delayMs) => new Promise((resolve) => {
|
|
70
|
+
retryTimeout = setTimeout(() => {
|
|
71
|
+
retryTimeout = null;
|
|
72
|
+
resolve();
|
|
73
|
+
}, delayMs);
|
|
74
|
+
});
|
|
75
|
+
setClient(null);
|
|
76
|
+
setReady(false);
|
|
77
|
+
const cancelConnection = ({ updateState }) => {
|
|
78
|
+
if (cancelled) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
cancelled = true;
|
|
82
|
+
clearRetryTimeout();
|
|
83
|
+
const currentClient = clientRef.current;
|
|
84
|
+
clientRef.current = null;
|
|
85
|
+
disposeClient(currentClient);
|
|
86
|
+
if (updateState) {
|
|
87
|
+
setClient(null);
|
|
88
|
+
setReady(false);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
cancelConnectionRef.current = () => cancelConnection({ updateState: true });
|
|
92
|
+
void (async () => {
|
|
93
|
+
let retryCount = 0;
|
|
94
|
+
while (!cancelled) {
|
|
95
|
+
let connectionInfo;
|
|
96
|
+
try {
|
|
97
|
+
setState('authorizing');
|
|
98
|
+
setError(null);
|
|
99
|
+
connectionInfo = await authorization();
|
|
100
|
+
}
|
|
101
|
+
catch (nextError) {
|
|
102
|
+
if (cancelled) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
setError(nextError);
|
|
106
|
+
setState('done');
|
|
107
|
+
setReady(false);
|
|
46
108
|
return;
|
|
47
|
-
const room = new meshagent_2.RoomClient({
|
|
48
|
-
protocolFactory: meshagent_2.WebSocketClientProtocol.createFactory({ url, token: jwt }),
|
|
49
|
-
});
|
|
50
|
-
setClient(room);
|
|
51
|
-
setState('connecting');
|
|
52
|
-
await room.start({
|
|
53
|
-
onDone: () => {
|
|
54
|
-
if (cancelled)
|
|
55
|
-
return;
|
|
56
|
-
setState('done');
|
|
57
|
-
},
|
|
58
|
-
onError: (e) => {
|
|
59
|
-
if (cancelled)
|
|
60
|
-
return;
|
|
61
|
-
setError(e);
|
|
62
|
-
setState('done');
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
if (enableMessaging) {
|
|
66
|
-
room.messaging.enable();
|
|
67
109
|
}
|
|
68
|
-
if (cancelled)
|
|
110
|
+
if (cancelled) {
|
|
69
111
|
return;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
112
|
+
}
|
|
113
|
+
let nextClient;
|
|
114
|
+
if (roomClientFactory != null) {
|
|
115
|
+
nextClient = roomClientFactory(connectionInfo);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
nextClient = new meshagent_1.RoomClient({
|
|
119
|
+
protocolFactory: meshagent_1.WebSocketClientProtocol.createFactory({
|
|
120
|
+
url: connectionInfo.roomUrl,
|
|
121
|
+
token: connectionInfo.jwt,
|
|
122
|
+
}),
|
|
123
|
+
oauthTokenRequestHandler: oauthTokenRequestHandler == null
|
|
124
|
+
? undefined
|
|
125
|
+
: (request) => oauthTokenRequestHandler(nextClient, request),
|
|
126
|
+
secretRequestHandler: secretRequestHandler == null
|
|
127
|
+
? undefined
|
|
128
|
+
: (request) => secretRequestHandler(nextClient, request),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
clientRef.current = nextClient;
|
|
132
|
+
setClient(nextClient);
|
|
133
|
+
setReady(false);
|
|
134
|
+
setState('connecting');
|
|
135
|
+
try {
|
|
136
|
+
await nextClient.start({
|
|
137
|
+
onDone: () => {
|
|
138
|
+
if (cancelled || clientRef.current !== nextClient) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
setReady(false);
|
|
142
|
+
setState('done');
|
|
143
|
+
},
|
|
144
|
+
onError: (nextError) => {
|
|
145
|
+
if (cancelled || clientRef.current !== nextClient) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
setError(nextError);
|
|
149
|
+
setReady(false);
|
|
150
|
+
setState('done');
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
if (enableMessaging) {
|
|
154
|
+
nextClient.messaging.enable();
|
|
155
|
+
}
|
|
156
|
+
if (cancelled || clientRef.current !== nextClient) {
|
|
157
|
+
disposeClient(nextClient);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
retryCount = 0;
|
|
161
|
+
setError(null);
|
|
162
|
+
setReady(true);
|
|
163
|
+
setState('ready');
|
|
164
|
+
onReady?.(nextClient);
|
|
75
165
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
166
|
+
}
|
|
167
|
+
catch (nextError) {
|
|
168
|
+
disposeClient(nextClient);
|
|
169
|
+
if (cancelled) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
setClient((currentClient) => currentClient === nextClient ? null : currentClient);
|
|
173
|
+
setReady(false);
|
|
174
|
+
setError(nextError);
|
|
175
|
+
if (!isRetryableConnectionError(nextError)) {
|
|
176
|
+
setState('done');
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
setState('retrying');
|
|
180
|
+
await waitForRetry(getRetryDelayMs(retryCount));
|
|
181
|
+
retryCount += 1;
|
|
182
|
+
}
|
|
78
183
|
}
|
|
79
|
-
};
|
|
80
|
-
connect();
|
|
184
|
+
})();
|
|
81
185
|
return () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
dispose();
|
|
186
|
+
cancelConnection({ updateState: false });
|
|
187
|
+
cancelConnectionRef.current = () => { };
|
|
85
188
|
};
|
|
86
|
-
|
|
87
|
-
|
|
189
|
+
}, [reconnectKey, enableMessaging, roomClientFactory]);
|
|
190
|
+
const dispose = () => {
|
|
191
|
+
cancelConnectionRef.current();
|
|
192
|
+
setState('done');
|
|
193
|
+
};
|
|
88
194
|
return {
|
|
89
195
|
client,
|
|
90
196
|
state,
|
|
@@ -100,48 +206,59 @@ function useRoomIndicators({ room, path }) {
|
|
|
100
206
|
const [typing, setTyping] = (0, react_1.useState)(false);
|
|
101
207
|
const [thinking, setThinking] = (0, react_1.useState)(false);
|
|
102
208
|
(0, react_1.useEffect)(() => {
|
|
103
|
-
if (!room)
|
|
209
|
+
if (!room) {
|
|
104
210
|
return;
|
|
105
|
-
|
|
211
|
+
}
|
|
212
|
+
setTyping(false);
|
|
213
|
+
setThinking(false);
|
|
214
|
+
const subscription = (0, subscribe_async_gen_1.subscribe)(room.listen(), {
|
|
106
215
|
next: (event) => {
|
|
107
|
-
if (event instanceof meshagent_1.RoomMessageEvent) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
typingMap.current[message.fromParticipantId] = setTimeout(() => {
|
|
122
|
-
delete typingMap.current[message.fromParticipantId];
|
|
123
|
-
setTyping(Object.keys(typingMap.current).length > 0);
|
|
124
|
-
}, 1000);
|
|
125
|
-
// Update typing state
|
|
216
|
+
if (!(event instanceof meshagent_1.RoomMessageEvent)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const { message } = event;
|
|
220
|
+
if (message.fromParticipantId === room.localParticipant?.id) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (message.message.path !== path) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (message.type === 'typing') {
|
|
227
|
+
clearTimeout(typingMap.current[message.fromParticipantId]);
|
|
228
|
+
typingMap.current[message.fromParticipantId] = setTimeout(() => {
|
|
229
|
+
delete typingMap.current[message.fromParticipantId];
|
|
126
230
|
setTyping(Object.keys(typingMap.current).length > 0);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
231
|
+
}, 1000);
|
|
232
|
+
setTyping(Object.keys(typingMap.current).length > 0);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (message.type !== 'thinking') {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
clearTimeout(thinkingMap.current[message.fromParticipantId]);
|
|
239
|
+
if (message.message.thinking) {
|
|
240
|
+
thinkingMap.current[message.fromParticipantId] = setTimeout(() => {
|
|
241
|
+
delete thinkingMap.current[message.fromParticipantId];
|
|
139
242
|
setThinking(Object.keys(thinkingMap.current).length > 0);
|
|
140
|
-
}
|
|
243
|
+
}, 5000);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
delete thinkingMap.current[message.fromParticipantId];
|
|
141
247
|
}
|
|
248
|
+
setThinking(Object.keys(thinkingMap.current).length > 0);
|
|
142
249
|
},
|
|
143
250
|
});
|
|
144
|
-
return () =>
|
|
145
|
-
|
|
251
|
+
return () => {
|
|
252
|
+
subscription.unsubscribe();
|
|
253
|
+
for (const timeout of Object.values(typingMap.current)) {
|
|
254
|
+
clearTimeout(timeout);
|
|
255
|
+
}
|
|
256
|
+
for (const timeout of Object.values(thinkingMap.current)) {
|
|
257
|
+
clearTimeout(timeout);
|
|
258
|
+
}
|
|
259
|
+
typingMap.current = {};
|
|
260
|
+
thinkingMap.current = {};
|
|
261
|
+
};
|
|
262
|
+
}, [path, room]);
|
|
146
263
|
return { typing, thinking };
|
|
147
264
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useRoomParticipants = useRoomParticipants;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function sameParticipantIds(currentParticipants, nextParticipants) {
|
|
6
|
+
if (currentParticipants.length !== nextParticipants.length) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const currentParticipantIds = new Set(currentParticipants.map((participant) => participant.id));
|
|
10
|
+
for (const participant of nextParticipants) {
|
|
11
|
+
if (!currentParticipantIds.has(participant.id)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
function useRoomParticipants(room) {
|
|
18
|
+
const [participants, setParticipants] = (0, react_1.useState)([]);
|
|
19
|
+
(0, react_1.useEffect)(() => {
|
|
20
|
+
if (room == null) {
|
|
21
|
+
setParticipants([]);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const updateParticipants = () => {
|
|
25
|
+
const nextParticipants = room.messaging.remoteParticipants;
|
|
26
|
+
setParticipants((currentParticipants) => {
|
|
27
|
+
if (sameParticipantIds(currentParticipants, nextParticipants)) {
|
|
28
|
+
return currentParticipants;
|
|
29
|
+
}
|
|
30
|
+
return [...nextParticipants];
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
room.messaging.on('participant_added', updateParticipants);
|
|
34
|
+
room.messaging.on('participant_removed', updateParticipants);
|
|
35
|
+
room.messaging.on('messaging_enabled', updateParticipants);
|
|
36
|
+
room.on('disconnected', updateParticipants);
|
|
37
|
+
updateParticipants();
|
|
38
|
+
return () => {
|
|
39
|
+
room.messaging.off('participant_added', updateParticipants);
|
|
40
|
+
room.messaging.off('participant_removed', updateParticipants);
|
|
41
|
+
room.messaging.off('messaging_enabled', updateParticipants);
|
|
42
|
+
room.off('disconnected', updateParticipants);
|
|
43
|
+
};
|
|
44
|
+
}, [room]);
|
|
45
|
+
return participants;
|
|
46
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { RoomClient, Toolkit } from
|
|
1
|
+
import { RoomClient, Toolkit } from "@meshagent/meshagent";
|
|
2
2
|
interface ClientToolkitsProps {
|
|
3
3
|
room: RoomClient;
|
|
4
4
|
toolkits: Toolkit[];
|
|
5
5
|
public?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare const useClientToolkits: ({ room, toolkits, public: isPublic }: ClientToolkitsProps) => void;
|
|
7
|
+
export declare const useClientToolkits: ({ room, toolkits, public: isPublic, }: ClientToolkitsProps) => void;
|
|
8
8
|
export {};
|