@microsoft/live-share-react 1.0.2-preview.1 → 1.2.0-preview.0
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/bin/live-hooks/index.d.ts +1 -0
- package/bin/live-hooks/index.d.ts.map +1 -1
- package/bin/live-hooks/index.js +1 -0
- package/bin/live-hooks/index.js.map +1 -1
- package/bin/live-hooks/useLiveEvent.d.ts.map +1 -1
- package/bin/live-hooks/useLiveEvent.js +2 -2
- package/bin/live-hooks/useLiveEvent.js.map +1 -1
- package/bin/live-hooks/useLiveFollowMode.d.ts +23 -0
- package/bin/live-hooks/useLiveFollowMode.d.ts.map +1 -0
- package/bin/live-hooks/useLiveFollowMode.js +212 -0
- package/bin/live-hooks/useLiveFollowMode.js.map +1 -0
- package/bin/live-hooks/useLivePresence.d.ts +1 -2
- package/bin/live-hooks/useLivePresence.d.ts.map +1 -1
- package/bin/live-hooks/useLivePresence.js +4 -4
- package/bin/live-hooks/useLivePresence.js.map +1 -1
- package/bin/live-hooks/useLiveState.d.ts.map +1 -1
- package/bin/live-hooks/useLiveState.js +2 -2
- package/bin/live-hooks/useLiveState.js.map +1 -1
- package/bin/live-hooks/useLiveTimer.d.ts.map +1 -1
- package/bin/live-hooks/useLiveTimer.js +2 -2
- package/bin/live-hooks/useLiveTimer.js.map +1 -1
- package/bin/live-hooks/useMediaSynchronizer.d.ts.map +1 -1
- package/bin/live-hooks/useMediaSynchronizer.js +3 -1
- package/bin/live-hooks/useMediaSynchronizer.js.map +1 -1
- package/bin/types/ResultTypes.d.ts +128 -1
- package/bin/types/ResultTypes.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/live-hooks/index.ts +1 -0
- package/src/live-hooks/useLiveEvent.ts +4 -1
- package/src/live-hooks/useLiveFollowMode.ts +315 -0
- package/src/live-hooks/useLivePresence.ts +6 -3
- package/src/live-hooks/useLiveState.ts +8 -2
- package/src/live-hooks/useLiveTimer.ts +4 -1
- package/src/live-hooks/useMediaSynchronizer.ts +8 -2
- package/src/types/ResultTypes.ts +131 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
import { AzureContainerServices } from "@fluidframework/azure-client";
|
|
6
|
-
import { ITimerConfig, LivePresenceUser, LiveEvent, LivePresence, LiveTimer } from "@microsoft/live-share";
|
|
6
|
+
import { ITimerConfig, LivePresenceUser, LiveEvent, LivePresence, LiveTimer, IFollowModeState, FollowModePresenceUser, LiveFollowMode } from "@microsoft/live-share";
|
|
7
7
|
import { InkingManager, LiveCanvas } from "@microsoft/live-share-canvas";
|
|
8
8
|
import { CoordinationWaitPoint, ExtendedMediaMetadata, MediaPlayerSynchronizer } from "@microsoft/live-share-media";
|
|
9
9
|
import { IFluidContainer, SharedMap } from "fluid-framework";
|
|
@@ -25,6 +25,9 @@ export interface ILiveShareContainerResults extends IAzureContainerResults {
|
|
|
25
25
|
*/
|
|
26
26
|
created: boolean;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Return type of `useSharedMap` hook.
|
|
30
|
+
*/
|
|
28
31
|
export interface IUseSharedMapResults<TData> {
|
|
29
32
|
/**
|
|
30
33
|
* Stateful map of most recent values from `SharedMap`.
|
|
@@ -43,6 +46,9 @@ export interface IUseSharedMapResults<TData> {
|
|
|
43
46
|
*/
|
|
44
47
|
sharedMap: SharedMap | undefined;
|
|
45
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Return type of `useLiveEvent` hook.
|
|
51
|
+
*/
|
|
46
52
|
export interface IUseLiveEventResults<TEvent = any> {
|
|
47
53
|
/**
|
|
48
54
|
* The most recent event that has been received in the session.
|
|
@@ -63,6 +69,9 @@ export interface IUseLiveEventResults<TEvent = any> {
|
|
|
63
69
|
*/
|
|
64
70
|
liveEvent: LiveEvent | undefined;
|
|
65
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Return type of `useLiveTimer` hook.
|
|
74
|
+
*/
|
|
66
75
|
export interface IUseLiveTimerResults {
|
|
67
76
|
/**
|
|
68
77
|
* The current timer configuration.
|
|
@@ -93,6 +102,9 @@ export interface IUseLiveTimerResults {
|
|
|
93
102
|
*/
|
|
94
103
|
pause: OnPauseTimerAction;
|
|
95
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Return type of `useLivePresence` hook.
|
|
107
|
+
*/
|
|
96
108
|
export interface IUseLivePresenceResults<TData extends object = object> {
|
|
97
109
|
/**
|
|
98
110
|
* The local user's presence object.
|
|
@@ -118,6 +130,9 @@ export interface IUseLivePresenceResults<TData extends object = object> {
|
|
|
118
130
|
*/
|
|
119
131
|
updatePresence: OnUpdateLivePresenceAction<TData>;
|
|
120
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Return type of `useMediaSynchronizer` hook.
|
|
135
|
+
*/
|
|
121
136
|
export interface IUseMediaSynchronizerResults {
|
|
122
137
|
/**
|
|
123
138
|
* Stateful boolean on whether the session has an active suspension.
|
|
@@ -162,6 +177,9 @@ export interface IUseMediaSynchronizerResults {
|
|
|
162
177
|
*/
|
|
163
178
|
mediaSynchronizer: MediaPlayerSynchronizer | undefined;
|
|
164
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Return type of `useLiveCanvas` hook.
|
|
182
|
+
*/
|
|
165
183
|
export interface IUseLiveCanvasResults {
|
|
166
184
|
/**
|
|
167
185
|
* Inking manager for the canvas, which is synchronized by `liveCanvas`. It is set when loaded and undefined while loading.
|
|
@@ -172,4 +190,113 @@ export interface IUseLiveCanvasResults {
|
|
|
172
190
|
*/
|
|
173
191
|
liveCanvas: LiveCanvas | undefined;
|
|
174
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Return type of `useLiveFollowMode` hook.
|
|
195
|
+
*/
|
|
196
|
+
export interface IUseLiveFollowModeResults<TData = any> {
|
|
197
|
+
/**
|
|
198
|
+
* Gets the current follow mode state.
|
|
199
|
+
*/
|
|
200
|
+
state: IFollowModeState<TData> | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Local LivePresenceUser.
|
|
203
|
+
*/
|
|
204
|
+
localUser: FollowModePresenceUser<TData> | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* List of non-local user's presence objects.
|
|
207
|
+
*/
|
|
208
|
+
otherUsers: FollowModePresenceUser<TData>[];
|
|
209
|
+
/**
|
|
210
|
+
* List of all user's presence objects.
|
|
211
|
+
*/
|
|
212
|
+
allUsers: FollowModePresenceUser<TData>[];
|
|
213
|
+
/**
|
|
214
|
+
* LiveFollowMode DDS
|
|
215
|
+
*/
|
|
216
|
+
liveFollowMode: LiveFollowMode<TData> | undefined;
|
|
217
|
+
/**
|
|
218
|
+
* Broadcast a new custom data value for the local user's current state.
|
|
219
|
+
*
|
|
220
|
+
* @remarks
|
|
221
|
+
* Each user has their own state value, though it will differ from what is shown in {@link state} depending on the value of {@link FollowModeType}.
|
|
222
|
+
* Will cause the user to become out of sync if another user is presenting or the local user is following another user.
|
|
223
|
+
* To see each user's state, use the {@link getUsers} API, or listen to "presenceChanged" updates.
|
|
224
|
+
*
|
|
225
|
+
* @param newValue the state value for the local user's presence record.
|
|
226
|
+
*
|
|
227
|
+
* @returns a void promise that resolves once the update event has been sent to the server.
|
|
228
|
+
*
|
|
229
|
+
* @throws error if initialization has not yet succeeded.
|
|
230
|
+
*/
|
|
231
|
+
update: (stateValue: TData) => Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* Start presenting the local user's state.
|
|
234
|
+
*
|
|
235
|
+
* @remarks
|
|
236
|
+
* If another user is already presenting, the local user will take control of presenting from the previous presenter.
|
|
237
|
+
* To update the local user's state that both the local and remote users will reference, use the {@link update} function.
|
|
238
|
+
* This API will override any `followingUserId` value that was set through {@link followUser} until presenting has stopped.
|
|
239
|
+
* To stop presenting, use the {@link stopPresenting} API.
|
|
240
|
+
*
|
|
241
|
+
* @returns a void promise that resolves once the event has been sent to the server.
|
|
242
|
+
*
|
|
243
|
+
* @throws error if initialization has not yet succeeded.
|
|
244
|
+
* @throws error if the local user is already the presenter.
|
|
245
|
+
* @throws error if the local user does not have the required roles to present.
|
|
246
|
+
*/
|
|
247
|
+
startPresenting: () => Promise<void>;
|
|
248
|
+
/**
|
|
249
|
+
* Stop presenting the presenting user's current state.
|
|
250
|
+
*
|
|
251
|
+
* @remarks
|
|
252
|
+
* This API allows any user with valid roles to cancel presenting, though we generally recommend only allowing the active presenter to do so.
|
|
253
|
+
* To start presenting, use the {@link startPresenting} API.
|
|
254
|
+
*
|
|
255
|
+
* @returns a void promise that resolves once the event has been sent to the server.
|
|
256
|
+
*
|
|
257
|
+
* @throws error if initialization has not yet succeeded.
|
|
258
|
+
* @throws error if the local user does not have the required roles to stop presenting.
|
|
259
|
+
*/
|
|
260
|
+
stopPresenting: () => Promise<void>;
|
|
261
|
+
/**
|
|
262
|
+
* Temporarily stop following presenter/follower.
|
|
263
|
+
*
|
|
264
|
+
* @returns a void promise once the operation succeeds.
|
|
265
|
+
*
|
|
266
|
+
* @throws error if initialization has not yet succeeded.
|
|
267
|
+
*/
|
|
268
|
+
beginSuspension: () => Promise<void>;
|
|
269
|
+
/**
|
|
270
|
+
* Resume following presenter/follower.
|
|
271
|
+
*
|
|
272
|
+
* @returns a void promise once the operation succeeds.
|
|
273
|
+
*
|
|
274
|
+
* @throws error if initialization has not yet succeeded.
|
|
275
|
+
*/
|
|
276
|
+
endSuspension: () => Promise<void>;
|
|
277
|
+
/**
|
|
278
|
+
* Follows another user in the session.
|
|
279
|
+
*
|
|
280
|
+
* @remarks
|
|
281
|
+
* If another user is presenting, {@link state} will not reflect following this user until there is no longer a presenter.
|
|
282
|
+
*
|
|
283
|
+
* @param userId the userId for the user to follow.
|
|
284
|
+
*
|
|
285
|
+
* @returns a void promise that resolves once the event has been sent to the server.
|
|
286
|
+
*
|
|
287
|
+
* @throws error if initialization has not yet succeeded.
|
|
288
|
+
* @throws error if attempting to follow a user that is not recognized by this object's `LivePresence` instance.
|
|
289
|
+
* @throws error if the `userId` provided is equal to the local user's `userId`.
|
|
290
|
+
*/
|
|
291
|
+
followUser: (userId: string) => Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Stop following the currently following user.
|
|
294
|
+
*
|
|
295
|
+
* @returns a void promise that resolves once the event has been sent to the server.
|
|
296
|
+
*
|
|
297
|
+
* @throws error if initialization has not yet succeeded.
|
|
298
|
+
* @throws error if the user is not already following another user.
|
|
299
|
+
*/
|
|
300
|
+
stopFollowing: () => Promise<void>;
|
|
301
|
+
}
|
|
175
302
|
//# sourceMappingURL=ResultTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultTypes.d.ts","sourceRoot":"","sources":["../../src/types/ResultTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EACH,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"ResultTypes.d.ts","sourceRoot":"","sources":["../../src/types/ResultTypes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/live-share-react",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0-preview.0",
|
|
4
4
|
"description": "Build collaborative React apps using Microsoft's Fluid & Live Share frameworks with ease.",
|
|
5
5
|
"author": "Microsoft",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"typecheck": "tsc"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@microsoft/live-share-turbo": "1.0
|
|
15
|
+
"@microsoft/live-share-turbo": "1.2.0-preview.0",
|
|
16
16
|
"url": "^0.11.0",
|
|
17
17
|
"uuid": "^9.0.0"
|
|
18
18
|
},
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"@babel/core": "^7.21.8",
|
|
21
21
|
"@fluidframework/azure-client": "^1.1.1",
|
|
22
22
|
"@fluidframework/test-client-utils": "^1.3.6",
|
|
23
|
-
"@microsoft/live-share": "1.0
|
|
24
|
-
"@microsoft/live-share-canvas": "1.0
|
|
25
|
-
"@microsoft/live-share-media": "1.0
|
|
23
|
+
"@microsoft/live-share": "1.2.0",
|
|
24
|
+
"@microsoft/live-share-canvas": "1.2.0",
|
|
25
|
+
"@microsoft/live-share-media": "1.2.0",
|
|
26
26
|
"@types/react": "^18.0.0",
|
|
27
27
|
"@types/react-dom": "^18.0.0",
|
|
28
28
|
"@types/uuid": "^9.0.1",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@fluidframework/azure-client": "^1.0.0",
|
|
35
|
-
"@microsoft/live-share": "1.0
|
|
36
|
-
"@microsoft/live-share-canvas": "1.0
|
|
37
|
-
"@microsoft/live-share-media": "1.0
|
|
35
|
+
"@microsoft/live-share": "1.2.0",
|
|
36
|
+
"@microsoft/live-share-canvas": "1.2.0",
|
|
37
|
+
"@microsoft/live-share-media": "1.2.0",
|
|
38
38
|
"fluid-framework": "^1.2.3",
|
|
39
39
|
"react": "^16.8.0 || ^17 || ^18",
|
|
40
40
|
"react-dom": "^16.8.0 || ^17 || ^18"
|
package/src/live-hooks/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
LiveEventEvents,
|
|
8
8
|
UserMeetingRole,
|
|
9
9
|
LiveEvent,
|
|
10
|
+
LiveDataObjectInitializeState,
|
|
10
11
|
} from "@microsoft/live-share";
|
|
11
12
|
import React from "react";
|
|
12
13
|
import {
|
|
@@ -116,7 +117,9 @@ export function useLiveEvent<TEvent = any>(
|
|
|
116
117
|
setLatestReceived(received);
|
|
117
118
|
};
|
|
118
119
|
liveEvent.on(LiveEventEvents.received, onEventReceived);
|
|
119
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
liveEvent.initializeState === LiveDataObjectInitializeState.needed
|
|
122
|
+
) {
|
|
120
123
|
// Start live event
|
|
121
124
|
liveEvent.initialize(allowedRoles);
|
|
122
125
|
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
LivePresenceUser,
|
|
8
|
+
UserMeetingRole,
|
|
9
|
+
LiveDataObjectInitializeState,
|
|
10
|
+
LiveFollowMode,
|
|
11
|
+
IFollowModePresenceUserData,
|
|
12
|
+
IFollowModeState,
|
|
13
|
+
} from "@microsoft/live-share";
|
|
14
|
+
import React from "react";
|
|
15
|
+
import { useDynamicDDS } from "../shared-hooks";
|
|
16
|
+
import { useFluidObjectsContext } from "../providers";
|
|
17
|
+
import {
|
|
18
|
+
ActionContainerNotJoinedError,
|
|
19
|
+
ActionLiveDataObjectInitializedError,
|
|
20
|
+
ActionLiveDataObjectUndefinedError,
|
|
21
|
+
} from "../internal";
|
|
22
|
+
import { IUseLiveFollowModeResults } from "../types";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* React hook for using a Live Share `LiveFollowMode`.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Use this hook if you want to add the ability to follow specific users or let a user present to everyone in the session.
|
|
29
|
+
* Each user has their own `stateValue`, which is the value other users will reference when that user is presenting or being followed.
|
|
30
|
+
* The `state` response includes the user's `value` that the local user is "following", whether it be their own or someone else's.
|
|
31
|
+
*
|
|
32
|
+
* @template TData Optional typing for the custom user presence data object. Default is `object` type.
|
|
33
|
+
*
|
|
34
|
+
* @param uniqueKey The unique key for `LiveFollowMode`. If one does not yet exist, a new one will be created.
|
|
35
|
+
* @param initialData The initial value for the local user's `stateValue`.
|
|
36
|
+
* @param allowedRoles Optional. The user roles that are allowed to present to use `startPresenting()` or `stopPresenting()`.
|
|
37
|
+
* @returns `IUseLiveFollowModeResults` results, which contains React stateful objects and callbacks.
|
|
38
|
+
*/
|
|
39
|
+
export function useLiveFollowMode<TData = any>(
|
|
40
|
+
uniqueKey: string,
|
|
41
|
+
initialData: TData | (() => TData),
|
|
42
|
+
allowedRoles?: UserMeetingRole[]
|
|
43
|
+
): IUseLiveFollowModeResults<TData> {
|
|
44
|
+
/**
|
|
45
|
+
* Stateful follow state.
|
|
46
|
+
*/
|
|
47
|
+
const [state, setState] = React.useState<IFollowModeState<TData>>();
|
|
48
|
+
/**
|
|
49
|
+
* Stateful all user presence list and its non-user-facing setter method.
|
|
50
|
+
*/
|
|
51
|
+
const [allUsers, setAllUsers] = React.useState<
|
|
52
|
+
LivePresenceUser<IFollowModePresenceUserData<TData>>[]
|
|
53
|
+
>([]);
|
|
54
|
+
/**
|
|
55
|
+
* User facing: dynamically load the DDS for the given unique key.
|
|
56
|
+
*/
|
|
57
|
+
const { dds: liveFollowMode } = useDynamicDDS<LiveFollowMode<TData>>(
|
|
58
|
+
uniqueKey,
|
|
59
|
+
LiveFollowMode<TData>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* User facing: list of non-local user's presence objects.
|
|
64
|
+
*/
|
|
65
|
+
const otherUsers = allUsers.filter((user) => !user.isLocalUser);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* User facing: local user's presence object.
|
|
69
|
+
*/
|
|
70
|
+
const localUser = allUsers.find((user) => user.isLocalUser);
|
|
71
|
+
|
|
72
|
+
const { container } = useFluidObjectsContext();
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* User facing: callback to update the local user's custom data for their follow state.
|
|
76
|
+
*/
|
|
77
|
+
const update = React.useCallback(
|
|
78
|
+
async (stateValue: TData) => {
|
|
79
|
+
if (!container) {
|
|
80
|
+
throw new ActionContainerNotJoinedError(
|
|
81
|
+
"liveFollowMode",
|
|
82
|
+
"updateState"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (liveFollowMode === undefined) {
|
|
86
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
87
|
+
"liveFollowMode",
|
|
88
|
+
"updateState"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (!liveFollowMode.isInitialized) {
|
|
92
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
93
|
+
"liveFollowMode",
|
|
94
|
+
"updateState"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return await liveFollowMode.update(stateValue);
|
|
98
|
+
},
|
|
99
|
+
[container, liveFollowMode]
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* User facing: callback to start presenting.
|
|
104
|
+
*/
|
|
105
|
+
const startPresenting = React.useCallback(async () => {
|
|
106
|
+
if (!container) {
|
|
107
|
+
throw new ActionContainerNotJoinedError(
|
|
108
|
+
"liveFollowMode",
|
|
109
|
+
"updateState"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (liveFollowMode === undefined) {
|
|
113
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
114
|
+
"liveFollowMode",
|
|
115
|
+
"updateState"
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (!liveFollowMode.isInitialized) {
|
|
119
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
120
|
+
"liveFollowMode",
|
|
121
|
+
"updateState"
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return await liveFollowMode.startPresenting();
|
|
125
|
+
}, [container, liveFollowMode]);
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* User facing: callback to stop presenting.
|
|
129
|
+
*/
|
|
130
|
+
const stopPresenting = React.useCallback(async () => {
|
|
131
|
+
if (!container) {
|
|
132
|
+
throw new ActionContainerNotJoinedError(
|
|
133
|
+
"liveFollowMode",
|
|
134
|
+
"stopPresenting"
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
if (liveFollowMode === undefined) {
|
|
138
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
139
|
+
"liveFollowMode",
|
|
140
|
+
"stopPresenting"
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
if (!liveFollowMode.isInitialized) {
|
|
144
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
145
|
+
"liveFollowMode",
|
|
146
|
+
"stopPresenting"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return await liveFollowMode.stopPresenting();
|
|
150
|
+
}, [container, liveFollowMode]);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* User facing: callback to suspend sync.
|
|
154
|
+
*/
|
|
155
|
+
const beginSuspension = React.useCallback(async () => {
|
|
156
|
+
if (!container) {
|
|
157
|
+
throw new ActionContainerNotJoinedError(
|
|
158
|
+
"liveFollowMode",
|
|
159
|
+
"syncToPresenter"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (liveFollowMode === undefined) {
|
|
163
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
164
|
+
"liveFollowMode",
|
|
165
|
+
"syncToPresenter"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (!liveFollowMode.isInitialized) {
|
|
169
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
170
|
+
"liveFollowMode",
|
|
171
|
+
"syncToPresenter"
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return await liveFollowMode.beginSuspension();
|
|
175
|
+
}, [container, liveFollowMode]);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* User facing: callback to end current suspension.
|
|
179
|
+
*/
|
|
180
|
+
const endSuspension = React.useCallback(async () => {
|
|
181
|
+
if (!container) {
|
|
182
|
+
throw new ActionContainerNotJoinedError(
|
|
183
|
+
"liveFollowMode",
|
|
184
|
+
"syncToPresenter"
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
if (liveFollowMode === undefined) {
|
|
188
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
189
|
+
"liveFollowMode",
|
|
190
|
+
"syncToPresenter"
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
if (!liveFollowMode.isInitialized) {
|
|
194
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
195
|
+
"liveFollowMode",
|
|
196
|
+
"syncToPresenter"
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
return await liveFollowMode.endSuspension();
|
|
200
|
+
}, [container, liveFollowMode]);
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* User facing: callback to follow a specific user.
|
|
204
|
+
*/
|
|
205
|
+
const followUser = React.useCallback(
|
|
206
|
+
async (userId: string) => {
|
|
207
|
+
if (!container) {
|
|
208
|
+
throw new ActionContainerNotJoinedError(
|
|
209
|
+
"liveFollowMode",
|
|
210
|
+
"followUser"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (liveFollowMode === undefined) {
|
|
214
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
215
|
+
"liveFollowMode",
|
|
216
|
+
"followUser"
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
if (!liveFollowMode.isInitialized) {
|
|
220
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
221
|
+
"liveFollowMode",
|
|
222
|
+
"followUser"
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return await liveFollowMode.followUser(userId);
|
|
226
|
+
},
|
|
227
|
+
[container, liveFollowMode]
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* User facing: callback to stop following a user.
|
|
232
|
+
*/
|
|
233
|
+
const stopFollowing = React.useCallback(async () => {
|
|
234
|
+
if (!container) {
|
|
235
|
+
throw new ActionContainerNotJoinedError(
|
|
236
|
+
"liveFollowMode",
|
|
237
|
+
"stopFollowing"
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
if (liveFollowMode === undefined) {
|
|
241
|
+
throw new ActionLiveDataObjectUndefinedError(
|
|
242
|
+
"liveFollowMode",
|
|
243
|
+
"stopFollowing"
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (!liveFollowMode.isInitialized) {
|
|
247
|
+
throw new ActionLiveDataObjectInitializedError(
|
|
248
|
+
"liveFollowMode",
|
|
249
|
+
"stopFollowing"
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return await liveFollowMode.stopFollowing();
|
|
253
|
+
}, [container, liveFollowMode]);
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Setup change listeners and start `LiveFollowMode` if needed
|
|
257
|
+
*/
|
|
258
|
+
React.useEffect(() => {
|
|
259
|
+
if (liveFollowMode === undefined) return;
|
|
260
|
+
|
|
261
|
+
const onPresenceChanged = () => {
|
|
262
|
+
const updatedLocalUsers: LivePresenceUser<
|
|
263
|
+
IFollowModePresenceUserData<TData>
|
|
264
|
+
>[] = [];
|
|
265
|
+
liveFollowMode?.getUsers().forEach((user) => {
|
|
266
|
+
updatedLocalUsers.push(user);
|
|
267
|
+
});
|
|
268
|
+
setAllUsers(updatedLocalUsers);
|
|
269
|
+
};
|
|
270
|
+
liveFollowMode.on("presenceChanged", onPresenceChanged);
|
|
271
|
+
const onStateChanged = () => {
|
|
272
|
+
setState(liveFollowMode?.state);
|
|
273
|
+
};
|
|
274
|
+
liveFollowMode.on("stateChanged", onStateChanged);
|
|
275
|
+
|
|
276
|
+
if (
|
|
277
|
+
liveFollowMode.initializeState ===
|
|
278
|
+
LiveDataObjectInitializeState.needed
|
|
279
|
+
) {
|
|
280
|
+
liveFollowMode.initialize(
|
|
281
|
+
isInitialDataCallback<TData>(initialData)
|
|
282
|
+
? initialData()
|
|
283
|
+
: initialData,
|
|
284
|
+
allowedRoles
|
|
285
|
+
);
|
|
286
|
+
} else {
|
|
287
|
+
onPresenceChanged();
|
|
288
|
+
onStateChanged();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return () => {
|
|
292
|
+
liveFollowMode?.off("presenceChanged", onPresenceChanged);
|
|
293
|
+
liveFollowMode?.off("stateChanged", onStateChanged);
|
|
294
|
+
};
|
|
295
|
+
}, [liveFollowMode]);
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
state,
|
|
299
|
+
localUser,
|
|
300
|
+
otherUsers,
|
|
301
|
+
allUsers,
|
|
302
|
+
liveFollowMode,
|
|
303
|
+
update,
|
|
304
|
+
startPresenting,
|
|
305
|
+
stopPresenting,
|
|
306
|
+
beginSuspension,
|
|
307
|
+
endSuspension,
|
|
308
|
+
followUser,
|
|
309
|
+
stopFollowing,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function isInitialDataCallback<TData>(value: any): value is () => TData {
|
|
314
|
+
return typeof value === "function";
|
|
315
|
+
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
PresenceState,
|
|
9
9
|
LivePresence,
|
|
10
10
|
UserMeetingRole,
|
|
11
|
+
LiveDataObjectInitializeState,
|
|
11
12
|
} from "@microsoft/live-share";
|
|
12
13
|
import React from "react";
|
|
13
14
|
import { IUseLivePresenceResults, OnUpdateLivePresenceAction } from "../types";
|
|
@@ -28,8 +29,7 @@ import {
|
|
|
28
29
|
* user data. This is useful for rendering a list of users, profile pictures, cursor positions, and more.
|
|
29
30
|
*
|
|
30
31
|
* @template TData Optional typing for the custom user presence data object. Default is `object` type.
|
|
31
|
-
* @param uniqueKey The unique key for `LivePresence`. If one does not yet exist, a new one
|
|
32
|
-
* @param userId Optional. The unique ID for a user. If none is provided, a random UUID will be generated.
|
|
32
|
+
* @param uniqueKey The unique key for `LivePresence`. If one does not yet exist, a new one will be created.
|
|
33
33
|
* @param initialData Optional. Initial presence data object for the user. Can be value or a function to get the value.
|
|
34
34
|
* @param initialPresenceState Optional. Initial status of the user's presence. Default is online.
|
|
35
35
|
* @param allowedRoles Optional. the user roles that are allowed to mutate the synchronized state
|
|
@@ -112,7 +112,10 @@ export function useLivePresence<TData extends object = object>(
|
|
|
112
112
|
};
|
|
113
113
|
livePresence.on("presenceChanged", onPresenceChanged);
|
|
114
114
|
|
|
115
|
-
if (
|
|
115
|
+
if (
|
|
116
|
+
livePresence.initializeState ===
|
|
117
|
+
LiveDataObjectInitializeState.needed
|
|
118
|
+
) {
|
|
116
119
|
livePresence.initialize(
|
|
117
120
|
isInitialDataCallback<TData>(initialData)
|
|
118
121
|
? initialData()
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
LiveDataObjectInitializeState,
|
|
8
|
+
LiveState,
|
|
9
|
+
UserMeetingRole,
|
|
10
|
+
} from "@microsoft/live-share";
|
|
7
11
|
import React from "react";
|
|
8
12
|
import { SetLiveStateAction } from "../types";
|
|
9
13
|
import { useDynamicDDS } from "../shared-hooks";
|
|
@@ -87,7 +91,9 @@ export function useLiveState<TState = any>(
|
|
|
87
91
|
setCurrentState(state);
|
|
88
92
|
};
|
|
89
93
|
liveState.on("stateChanged", onStateChanged);
|
|
90
|
-
if (
|
|
94
|
+
if (
|
|
95
|
+
liveState.initializeState === LiveDataObjectInitializeState.needed
|
|
96
|
+
) {
|
|
91
97
|
liveState.initialize(initialState, allowedRoles);
|
|
92
98
|
}
|
|
93
99
|
if (JSON.stringify(liveState.state) !== JSON.stringify(initialState)) {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
LiveTimerEvents,
|
|
9
9
|
UserMeetingRole,
|
|
10
10
|
LiveTimer,
|
|
11
|
+
LiveDataObjectInitializeState,
|
|
11
12
|
} from "@microsoft/live-share";
|
|
12
13
|
import React from "react";
|
|
13
14
|
import {
|
|
@@ -154,7 +155,9 @@ export function useLiveTimer(
|
|
|
154
155
|
liveTimer.on(LiveTimerEvents.played, onDidPlay);
|
|
155
156
|
liveTimer.on(LiveTimerEvents.paused, onDidPause);
|
|
156
157
|
liveTimer.on(LiveTimerEvents.onTick, onDidTick);
|
|
157
|
-
if (
|
|
158
|
+
if (
|
|
159
|
+
liveTimer.initializeState === LiveDataObjectInitializeState.needed
|
|
160
|
+
) {
|
|
158
161
|
// Start live event
|
|
159
162
|
liveTimer.initialize(allowedRoles);
|
|
160
163
|
}
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
LiveDataObjectInitializeState,
|
|
8
|
+
UserMeetingRole,
|
|
9
|
+
} from "@microsoft/live-share";
|
|
7
10
|
import React from "react";
|
|
8
11
|
import {
|
|
9
12
|
CoordinationWaitPoint,
|
|
@@ -211,7 +214,10 @@ export function useMediaSynchronizer(
|
|
|
211
214
|
synchronizer.viewOnly = viewOnly;
|
|
212
215
|
}
|
|
213
216
|
|
|
214
|
-
if (
|
|
217
|
+
if (
|
|
218
|
+
mediaSession.initializeState ===
|
|
219
|
+
LiveDataObjectInitializeState.needed
|
|
220
|
+
) {
|
|
215
221
|
// Start synchronizing the media session
|
|
216
222
|
mediaSession.initialize(allowedRoles ?? []);
|
|
217
223
|
} else if (initialTrack) {
|