@microsoft/live-share-react 1.0.0-preview.11 → 1.0.0-preview.13

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.
Files changed (215) hide show
  1. package/README.md +3 -3
  2. package/bin/index.d.ts +7 -0
  3. package/bin/index.d.ts.map +1 -0
  4. package/bin/index.js +7 -0
  5. package/bin/index.js.map +1 -0
  6. package/bin/interfaces/LiveInterfaceExtensions.d.ts +9 -0
  7. package/bin/interfaces/LiveInterfaceExtensions.d.ts.map +1 -0
  8. package/bin/interfaces/LiveInterfaceExtensions.js +6 -0
  9. package/bin/interfaces/LiveInterfaceExtensions.js.map +1 -0
  10. package/bin/interfaces/index.d.ts +2 -0
  11. package/bin/interfaces/index.d.ts.map +1 -0
  12. package/bin/interfaces/index.js +2 -0
  13. package/bin/interfaces/index.js.map +1 -0
  14. package/bin/internal-hooks/index.d.ts +2 -0
  15. package/bin/internal-hooks/index.d.ts.map +1 -0
  16. package/bin/internal-hooks/index.js +2 -0
  17. package/bin/internal-hooks/index.js.map +1 -0
  18. package/bin/internal-hooks/useDynamicDDSRegistry.d.ts +14 -0
  19. package/bin/internal-hooks/useDynamicDDSRegistry.d.ts.map +1 -0
  20. package/bin/internal-hooks/useDynamicDDSRegistry.js +142 -0
  21. package/bin/internal-hooks/useDynamicDDSRegistry.js.map +1 -0
  22. package/bin/internal-hooks/useSharedStateRegistry.d.ts +31 -0
  23. package/bin/internal-hooks/useSharedStateRegistry.d.ts.map +1 -0
  24. package/bin/internal-hooks/useSharedStateRegistry.js +102 -0
  25. package/bin/internal-hooks/useSharedStateRegistry.js.map +1 -0
  26. package/bin/internal-hooks/useStateRef.d.ts +7 -0
  27. package/bin/internal-hooks/useStateRef.d.ts.map +1 -0
  28. package/bin/internal-hooks/useStateRef.js +15 -0
  29. package/bin/internal-hooks/useStateRef.js.map +1 -0
  30. package/bin/live-hooks/index.d.ts +7 -0
  31. package/bin/live-hooks/index.d.ts.map +1 -0
  32. package/bin/live-hooks/index.js +7 -0
  33. package/bin/live-hooks/index.js.map +1 -0
  34. package/bin/live-hooks/useLiveAICompletion.d.ts +29 -0
  35. package/bin/live-hooks/useLiveAICompletion.d.ts.map +1 -0
  36. package/bin/live-hooks/useLiveAICompletion.js +186 -0
  37. package/bin/live-hooks/useLiveAICompletion.js.map +1 -0
  38. package/bin/live-hooks/useLiveCanvas.d.ts +28 -0
  39. package/bin/live-hooks/useLiveCanvas.d.ts.map +1 -0
  40. package/bin/live-hooks/useLiveCanvas.js +159 -0
  41. package/bin/live-hooks/useLiveCanvas.js.map +1 -0
  42. package/bin/live-hooks/useLiveCoPilot.d.ts +28 -0
  43. package/bin/live-hooks/useLiveCoPilot.d.ts.map +1 -0
  44. package/bin/live-hooks/useLiveCoPilot.js +178 -0
  45. package/bin/live-hooks/useLiveCoPilot.js.map +1 -0
  46. package/bin/live-hooks/useLiveEvent.d.ts +22 -0
  47. package/bin/live-hooks/useLiveEvent.d.ts.map +1 -0
  48. package/bin/live-hooks/useLiveEvent.js +93 -0
  49. package/bin/live-hooks/useLiveEvent.js.map +1 -0
  50. package/bin/live-hooks/useLivePresence.d.ts +26 -0
  51. package/bin/live-hooks/useLivePresence.d.ts.map +1 -0
  52. package/bin/live-hooks/useLivePresence.js +102 -0
  53. package/bin/live-hooks/useLivePresence.js.map +1 -0
  54. package/bin/live-hooks/useLiveState.d.ts +20 -0
  55. package/bin/live-hooks/useLiveState.d.ts.map +1 -0
  56. package/bin/live-hooks/useLiveState.js +73 -0
  57. package/bin/live-hooks/useLiveState.js.map +1 -0
  58. package/bin/live-hooks/useLiveTimer.d.ts +8 -0
  59. package/bin/live-hooks/useLiveTimer.d.ts.map +1 -0
  60. package/bin/live-hooks/useLiveTimer.js +145 -0
  61. package/bin/live-hooks/useLiveTimer.js.map +1 -0
  62. package/bin/live-hooks/useMediaSynchronizer.d.ts +23 -0
  63. package/bin/live-hooks/useMediaSynchronizer.d.ts.map +1 -0
  64. package/bin/live-hooks/useMediaSynchronizer.js +185 -0
  65. package/bin/live-hooks/useMediaSynchronizer.js.map +1 -0
  66. package/bin/live-share-turbo/AzureTurboClient.d.ts +39 -0
  67. package/bin/live-share-turbo/AzureTurboClient.d.ts.map +1 -0
  68. package/bin/live-share-turbo/AzureTurboClient.js +56 -0
  69. package/bin/live-share-turbo/AzureTurboClient.js.map +1 -0
  70. package/bin/live-share-turbo/LiveShareTurboClient.d.ts +53 -0
  71. package/bin/live-share-turbo/LiveShareTurboClient.d.ts.map +1 -0
  72. package/bin/live-share-turbo/LiveShareTurboClient.js +69 -0
  73. package/bin/live-share-turbo/LiveShareTurboClient.js.map +1 -0
  74. package/bin/live-share-turbo/dds-objects/TurboDataObject.d.ts +31 -0
  75. package/bin/live-share-turbo/dds-objects/TurboDataObject.d.ts.map +1 -0
  76. package/bin/live-share-turbo/dds-objects/TurboDataObject.js +75 -0
  77. package/bin/live-share-turbo/dds-objects/TurboDataObject.js.map +1 -0
  78. package/bin/live-share-turbo/dds-objects/TurboLiveCanvas.d.ts +48 -0
  79. package/bin/live-share-turbo/dds-objects/TurboLiveCanvas.d.ts.map +1 -0
  80. package/bin/live-share-turbo/dds-objects/TurboLiveCanvas.js +104 -0
  81. package/bin/live-share-turbo/dds-objects/TurboLiveCanvas.js.map +1 -0
  82. package/bin/live-share-turbo/dds-objects/TurboLiveEvent.d.ts +28 -0
  83. package/bin/live-share-turbo/dds-objects/TurboLiveEvent.d.ts.map +1 -0
  84. package/bin/live-share-turbo/dds-objects/TurboLiveEvent.js +68 -0
  85. package/bin/live-share-turbo/dds-objects/TurboLiveEvent.js.map +1 -0
  86. package/bin/live-share-turbo/dds-objects/TurboLiveMediaSession.d.ts +60 -0
  87. package/bin/live-share-turbo/dds-objects/TurboLiveMediaSession.d.ts.map +1 -0
  88. package/bin/live-share-turbo/dds-objects/TurboLiveMediaSession.js +111 -0
  89. package/bin/live-share-turbo/dds-objects/TurboLiveMediaSession.js.map +1 -0
  90. package/bin/live-share-turbo/dds-objects/TurboLivePresence.d.ts +77 -0
  91. package/bin/live-share-turbo/dds-objects/TurboLivePresence.d.ts.map +1 -0
  92. package/bin/live-share-turbo/dds-objects/TurboLivePresence.js +137 -0
  93. package/bin/live-share-turbo/dds-objects/TurboLivePresence.js.map +1 -0
  94. package/bin/live-share-turbo/dds-objects/TurboLiveState.d.ts +30 -0
  95. package/bin/live-share-turbo/dds-objects/TurboLiveState.d.ts.map +1 -0
  96. package/bin/live-share-turbo/dds-objects/TurboLiveState.js +74 -0
  97. package/bin/live-share-turbo/dds-objects/TurboLiveState.js.map +1 -0
  98. package/bin/live-share-turbo/dds-objects/TurboSharedMap.d.ts +61 -0
  99. package/bin/live-share-turbo/dds-objects/TurboSharedMap.d.ts.map +1 -0
  100. package/bin/live-share-turbo/dds-objects/TurboSharedMap.js +108 -0
  101. package/bin/live-share-turbo/dds-objects/TurboSharedMap.js.map +1 -0
  102. package/bin/live-share-turbo/dds-objects/index.d.ts +8 -0
  103. package/bin/live-share-turbo/dds-objects/index.d.ts.map +1 -0
  104. package/bin/live-share-turbo/dds-objects/index.js +8 -0
  105. package/bin/live-share-turbo/dds-objects/index.js.map +1 -0
  106. package/bin/live-share-turbo/index.d.ts +5 -0
  107. package/bin/live-share-turbo/index.d.ts.map +1 -0
  108. package/bin/live-share-turbo/index.js +5 -0
  109. package/bin/live-share-turbo/index.js.map +1 -0
  110. package/bin/live-share-turbo/interfaces/IFluidTurboClient.d.ts +15 -0
  111. package/bin/live-share-turbo/interfaces/IFluidTurboClient.d.ts.map +1 -0
  112. package/bin/live-share-turbo/interfaces/IFluidTurboClient.js +2 -0
  113. package/bin/live-share-turbo/interfaces/IFluidTurboClient.js.map +1 -0
  114. package/bin/live-share-turbo/interfaces/index.d.ts +3 -0
  115. package/bin/live-share-turbo/interfaces/index.d.ts.map +1 -0
  116. package/bin/live-share-turbo/interfaces/index.js +3 -0
  117. package/bin/live-share-turbo/interfaces/index.js.map +1 -0
  118. package/bin/live-share-turbo/internals/FluidTurboClient.d.ts +39 -0
  119. package/bin/live-share-turbo/internals/FluidTurboClient.d.ts.map +1 -0
  120. package/bin/live-share-turbo/internals/FluidTurboClient.js +121 -0
  121. package/bin/live-share-turbo/internals/FluidTurboClient.js.map +1 -0
  122. package/bin/live-share-turbo/internals/index.d.ts +2 -0
  123. package/bin/live-share-turbo/internals/index.d.ts.map +1 -0
  124. package/bin/live-share-turbo/internals/index.js +2 -0
  125. package/bin/live-share-turbo/internals/index.js.map +1 -0
  126. package/bin/live-share-turbo/internals/types.d.ts +4 -0
  127. package/bin/live-share-turbo/internals/types.d.ts.map +1 -0
  128. package/bin/live-share-turbo/internals/types.js +2 -0
  129. package/bin/live-share-turbo/internals/types.js.map +1 -0
  130. package/bin/providers/AzureProvider.d.ts +34 -0
  131. package/bin/providers/AzureProvider.d.ts.map +1 -0
  132. package/bin/providers/AzureProvider.js +102 -0
  133. package/bin/providers/AzureProvider.js.map +1 -0
  134. package/bin/providers/FluidContextProvider.d.ts +34 -0
  135. package/bin/providers/FluidContextProvider.d.ts.map +1 -0
  136. package/bin/providers/FluidContextProvider.js +99 -0
  137. package/bin/providers/FluidContextProvider.js.map +1 -0
  138. package/bin/providers/LiveShareContextProvider.d.ts +42 -0
  139. package/bin/providers/LiveShareContextProvider.d.ts.map +1 -0
  140. package/bin/providers/LiveShareContextProvider.js +63 -0
  141. package/bin/providers/LiveShareContextProvider.js.map +1 -0
  142. package/bin/providers/LiveShareProvider.d.ts +63 -0
  143. package/bin/providers/LiveShareProvider.d.ts.map +1 -0
  144. package/bin/providers/LiveShareProvider.js +69 -0
  145. package/bin/providers/LiveShareProvider.js.map +1 -0
  146. package/bin/providers/index.d.ts +3 -0
  147. package/bin/providers/index.d.ts.map +1 -0
  148. package/bin/providers/index.js +3 -0
  149. package/bin/providers/index.js.map +1 -0
  150. package/bin/shared-hooks/index.d.ts +4 -0
  151. package/bin/shared-hooks/index.d.ts.map +1 -0
  152. package/bin/shared-hooks/index.js +4 -0
  153. package/bin/shared-hooks/index.js.map +1 -0
  154. package/bin/shared-hooks/useDynamicDDS.d.ts +19 -0
  155. package/bin/shared-hooks/useDynamicDDS.d.ts.map +1 -0
  156. package/bin/shared-hooks/useDynamicDDS.js +68 -0
  157. package/bin/shared-hooks/useDynamicDDS.js.map +1 -0
  158. package/bin/shared-hooks/useLockedTask.d.ts +11 -0
  159. package/bin/shared-hooks/useLockedTask.d.ts.map +1 -0
  160. package/bin/shared-hooks/useLockedTask.js +82 -0
  161. package/bin/shared-hooks/useLockedTask.js.map +1 -0
  162. package/bin/shared-hooks/useSharedMap.d.ts +22 -0
  163. package/bin/shared-hooks/useSharedMap.d.ts.map +1 -0
  164. package/bin/shared-hooks/useSharedMap.js +106 -0
  165. package/bin/shared-hooks/useSharedMap.js.map +1 -0
  166. package/bin/shared-hooks/useSharedState.d.ts +21 -0
  167. package/bin/shared-hooks/useSharedState.d.ts.map +1 -0
  168. package/bin/shared-hooks/useSharedState.js +67 -0
  169. package/bin/shared-hooks/useSharedState.js.map +1 -0
  170. package/bin/shared-hooks/useTaskManager.d.ts +13 -0
  171. package/bin/shared-hooks/useTaskManager.d.ts.map +1 -0
  172. package/bin/shared-hooks/useTaskManager.js +86 -0
  173. package/bin/shared-hooks/useTaskManager.js.map +1 -0
  174. package/bin/types/ActionTypes.d.ts +106 -0
  175. package/bin/types/ActionTypes.d.ts.map +1 -0
  176. package/bin/types/ActionTypes.js +6 -0
  177. package/bin/types/ActionTypes.js.map +1 -0
  178. package/bin/types/PropTypes.d.ts +8 -0
  179. package/bin/types/PropTypes.d.ts.map +1 -0
  180. package/bin/types/PropTypes.js +6 -0
  181. package/bin/types/PropTypes.js.map +1 -0
  182. package/bin/types/ResultTypes.d.ts +175 -0
  183. package/bin/types/ResultTypes.d.ts.map +1 -0
  184. package/bin/types/ResultTypes.js +6 -0
  185. package/bin/types/ResultTypes.js.map +1 -0
  186. package/bin/types/index.d.ts +4 -0
  187. package/bin/types/index.d.ts.map +1 -0
  188. package/bin/types/index.js +4 -0
  189. package/bin/types/index.js.map +1 -0
  190. package/bin/utils/getContainerSchema.d.ts +8 -0
  191. package/bin/utils/getContainerSchema.d.ts.map +1 -0
  192. package/bin/utils/getContainerSchema.js +41 -0
  193. package/bin/utils/getContainerSchema.js.map +1 -0
  194. package/bin/utils/index.d.ts +2 -0
  195. package/bin/utils/index.d.ts.map +1 -0
  196. package/bin/utils/index.js +2 -0
  197. package/bin/utils/index.js.map +1 -0
  198. package/bin/utils/type-check.d.ts +15 -0
  199. package/bin/utils/type-check.d.ts.map +1 -0
  200. package/bin/utils/type-check.js +54 -0
  201. package/bin/utils/type-check.js.map +1 -0
  202. package/package.json +13 -13
  203. package/src/internal-hooks/useSharedStateRegistry.ts +6 -5
  204. package/src/live-hooks/useLiveEvent.ts +14 -18
  205. package/src/live-hooks/useLivePresence.ts +13 -7
  206. package/src/live-hooks/useLiveState.ts +8 -6
  207. package/src/live-hooks/useLiveTimer.ts +21 -18
  208. package/src/live-hooks/useMediaSynchronizer.ts +37 -27
  209. package/src/providers/AzureProvider.tsx +2 -7
  210. package/src/providers/LiveShareProvider.tsx +45 -15
  211. package/src/shared-hooks/useDynamicDDS.ts +15 -8
  212. package/src/shared-hooks/useSharedMap.ts +17 -10
  213. package/src/shared-hooks/useSharedState.ts +5 -1
  214. package/src/types/ActionTypes.ts +89 -11
  215. package/src/types/ResultTypes.ts +22 -8
@@ -18,15 +18,15 @@ import { useDynamicDDS } from "../shared-hooks";
18
18
  * @param initialState Optional. the initial state value of type TState
19
19
  * @param allowedRoles Optional. the user roles that are allowed to mutate the synchronized state
20
20
  * @returns ordered values: first value is the synchronized state value and the second is a setter to change the state value.
21
+ * The setter returns a void promise, which will throw if the user does not have the required roles to set.
21
22
  */
22
- export function useLiveState<
23
- TState = any,
24
- >(
23
+ export function useLiveState<TState = any>(
25
24
  uniqueKey: string,
26
25
  initialState: TState,
27
26
  allowedRoles?: UserMeetingRole[]
28
27
  ): [TState, SetLiveStateAction<TState>] {
29
- const [currentState, setCurrentState] = React.useState<TState>(initialState);
28
+ const [currentState, setCurrentState] =
29
+ React.useState<TState>(initialState);
30
30
  /**
31
31
  * User facing: dynamically load the DDS for the given unique key.
32
32
  */
@@ -37,9 +37,11 @@ export function useLiveState<
37
37
 
38
38
  /**
39
39
  * Change state callback that is user facing
40
+ * @param state TState to set
41
+ * @returns void promise, which will throw if the user does not have the required roles
40
42
  */
41
43
  const setState = React.useCallback(
42
- (state: TState) => {
44
+ async (state: TState) => {
43
45
  if (!liveState) {
44
46
  console.error(
45
47
  new Error(
@@ -56,7 +58,7 @@ export function useLiveState<
56
58
  );
57
59
  return;
58
60
  }
59
- liveState.set(state);
61
+ return await liveState.set(state);
60
62
  },
61
63
  [liveState]
62
64
  );
@@ -31,7 +31,7 @@ export function useLiveTimer(
31
31
  onStart?: OnTimerDidStartAction,
32
32
  onPause?: OnTimerDidPauseAction,
33
33
  onPlay?: OnTimerDidPlayAction,
34
- onFinish?: OnTimerDidFinishAction,
34
+ onFinish?: OnTimerDidFinishAction
35
35
  ): IUseLiveTimerResults {
36
36
  /**
37
37
  * User facing: Stateful timer config.
@@ -47,11 +47,13 @@ export function useLiveTimer(
47
47
  const { dds: liveTimer } = useDynamicDDS<LiveTimer>(uniqueKey, LiveTimer);
48
48
 
49
49
  /**
50
- * User facing: callback to send event through `LiveTimer`
50
+ * Callback to send event through `LiveTimer`
51
+ * @param duration the duration for the timer in milliseconds
52
+ * @returns void promise that will throw when user does not have required roles
51
53
  */
52
54
  const start: OnStartTimerAction = React.useCallback(
53
- (duration: number): void => {
54
- if (liveTimer?.isInitialized === undefined) {
55
+ async (duration: number) => {
56
+ if (liveTimer === undefined) {
55
57
  console.error(
56
58
  new Error("Cannot call start when liveTimer is undefined")
57
59
  );
@@ -65,16 +67,17 @@ export function useLiveTimer(
65
67
  );
66
68
  return;
67
69
  }
68
- liveTimer?.start(duration);
70
+ return await liveTimer.start(duration);
69
71
  },
70
- [liveTimer?.isInitialized]
72
+ [liveTimer]
71
73
  );
72
74
 
73
75
  /**
74
- * User facing: callback to send event through `LiveTimer`
76
+ * Callback to send event through `LiveTimer`
77
+ * @returns void promise that will throw when user does not have required roles
75
78
  */
76
- const play: OnPlayTimerAction = React.useCallback((): void => {
77
- if (liveTimer?.isInitialized === undefined) {
79
+ const play: OnPlayTimerAction = React.useCallback(async () => {
80
+ if (liveTimer === undefined) {
78
81
  console.error(
79
82
  new Error("Cannot call play when liveTimer is undefined")
80
83
  );
@@ -86,14 +89,15 @@ export function useLiveTimer(
86
89
  );
87
90
  return;
88
91
  }
89
- liveTimer?.play();
90
- }, [liveTimer?.isInitialized]);
92
+ return await liveTimer.play();
93
+ }, [liveTimer]);
91
94
 
92
95
  /**
93
- * User facing: callback to send event through `LiveTimer`
96
+ * Callback to send event through `LiveTimer`
97
+ * @returns void promise that will throw when user does not have required roles
94
98
  */
95
- const pause: OnPauseTimerAction = React.useCallback((): void => {
96
- if (liveTimer?.isInitialized === undefined) {
99
+ const pause: OnPauseTimerAction = React.useCallback(async () => {
100
+ if (liveTimer === undefined) {
97
101
  console.error(
98
102
  new Error("Cannot call pause when liveTimer is undefined")
99
103
  );
@@ -105,15 +109,14 @@ export function useLiveTimer(
105
109
  );
106
110
  return;
107
111
  }
108
- liveTimer?.pause();
109
- }, [liveTimer?.isInitialized]);
112
+ return await liveTimer.pause();
113
+ }, [liveTimer]);
110
114
 
111
115
  /**
112
116
  * Setup change listeners and start `LiveTimer` if needed
113
117
  */
114
118
  React.useEffect(() => {
115
- if (liveTimer === undefined)
116
- return;
119
+ if (liveTimer === undefined) return;
117
120
  // Register event listeners
118
121
  const onTimerConfigChange = (config: ITimerConfig) => {
119
122
  setTimerConfig(config);
@@ -52,28 +52,34 @@ export function useMediaSynchronizer(
52
52
  /**
53
53
  * User facing: dynamically load the LiveMediaSession DDS for the given unique key.
54
54
  */
55
- const { dds: mediaSession } = useDynamicDDS<LiveMediaSession>(uniqueKey, LiveMediaSession);
55
+ const { dds: mediaSession } = useDynamicDDS<LiveMediaSession>(
56
+ uniqueKey,
57
+ LiveMediaSession
58
+ );
56
59
 
57
60
  /**
58
- * User facing: play callback
61
+ * Play callback
59
62
  */
60
- const play = React.useCallback((): void => {
61
- mediaSynchronizer?.play();
63
+ const play = React.useCallback(async () => {
64
+ if (!mediaSynchronizer) return;
65
+ return await mediaSynchronizer.play();
62
66
  }, [mediaSynchronizer]);
63
67
 
64
68
  /**
65
- * User facing: pause callback
69
+ * Pause callback
66
70
  */
67
- const pause = React.useCallback((): void => {
68
- mediaSynchronizer?.pause();
71
+ const pause = React.useCallback(async () => {
72
+ if (!mediaSynchronizer) return;
73
+ return await mediaSynchronizer.pause();
69
74
  }, [mediaSynchronizer]);
70
75
 
71
76
  /**
72
77
  * User facing: seek callback
73
78
  */
74
79
  const seekTo = React.useCallback(
75
- (time: number): void => {
76
- mediaSynchronizer?.seekTo(time);
80
+ async (time: number) => {
81
+ if (!mediaSynchronizer) return;
82
+ return await mediaSynchronizer.seekTo(time);
77
83
  },
78
84
  [mediaSynchronizer]
79
85
  );
@@ -82,12 +88,12 @@ export function useMediaSynchronizer(
82
88
  * User facing: set track callback
83
89
  */
84
90
  const setTrack = React.useCallback(
85
- (track: Partial<ExtendedMediaMetadata> | string | null): void => {
86
- // TODO: fix force unwrap once synchronizer uses correct types
91
+ async (track: Partial<ExtendedMediaMetadata> | string | null) => {
92
+ if (!mediaSynchronizer) return;
87
93
  if (isExtendedMediaMetadata(track)) {
88
- mediaSynchronizer!.setTrack(track);
94
+ return await mediaSynchronizer.setTrack(track);
89
95
  } else if (typeof track === "string") {
90
- mediaSynchronizer!.setTrack({
96
+ return await mediaSynchronizer.setTrack({
91
97
  trackIdentifier: track,
92
98
  } as ExtendedMediaMetadata);
93
99
  }
@@ -119,8 +125,8 @@ export function useMediaSynchronizer(
119
125
  * Setup change listeners and start `LiveMediaSession` if needed
120
126
  */
121
127
  React.useEffect(() => {
122
- if (mediaSession === undefined || !mediaPlayerElementRef)
123
- return;
128
+ if (mediaSession === undefined || !mediaPlayerElementRef) return;
129
+ let mounted = true;
124
130
  // Query the HTML5 media element from the document and set reference
125
131
  let mediaPlayer: IMediaPlayer | undefined;
126
132
  if (isRefObject<IMediaPlayer>(mediaPlayerElementRef)) {
@@ -152,25 +158,29 @@ export function useMediaSynchronizer(
152
158
  // Start synchronizing the media session
153
159
  mediaSession.initialize(allowedRoles ?? []);
154
160
  } else if (initialTrack) {
155
- // If we have already started the media session, the synchronizer won't have initial track
156
- // data now that we are remounting.
157
- // TODO: if player is loaded twice in one app at once, then this has a chance to disrupt the
158
- // group state by resetting the track. MediaPlayerSynchronizer does not currently have a way to
159
- // get the current track, so to fix this we need a better solution.
160
- if (isExtendedMediaMetadata(initialTrack)) {
161
- synchronizer.setTrack(initialTrack);
162
- } else if (typeof initialTrack === "string") {
163
- synchronizer.setTrack({
164
- trackIdentifier: initialTrack,
165
- } as ExtendedMediaMetadata);
166
- }
161
+ mediaSession.onLocalUserAllowed(async () => {
162
+ if (!mounted) return;
163
+ try {
164
+ if (isExtendedMediaMetadata(initialTrack)) {
165
+ await synchronizer.setTrack(initialTrack);
166
+ } else if (typeof initialTrack === "string") {
167
+ await synchronizer.setTrack({
168
+ trackIdentifier: initialTrack,
169
+ } as ExtendedMediaMetadata);
170
+ }
171
+ } catch (err) {
172
+ console.error(err);
173
+ }
174
+ });
167
175
  }
168
176
  setMediaSynchronizer(synchronizer);
169
177
 
170
178
  return () => {
179
+ mounted = false;
171
180
  synchronizer.removeAllListeners();
172
181
  mediaSession.removeAllListeners();
173
182
  synchronizer?.end();
183
+ mediaSession?.dispose();
174
184
  };
175
185
  }, [mediaSession]);
176
186
 
@@ -3,10 +3,7 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import {
7
- IFluidContainer,
8
- LoadableObjectClassRecord,
9
- } from "fluid-framework";
6
+ import { IFluidContainer, LoadableObjectClassRecord } from "fluid-framework";
10
7
  import React from "react";
11
8
  import {
12
9
  AzureClientProps,
@@ -58,9 +55,7 @@ interface IAzureProviderProps {
58
55
  /**
59
56
  * React Context provider component for using Fluid data objects & joining/creating a Fluid document `AzureClient`.
60
57
  */
61
- export const AzureProvider: React.FC<IAzureProviderProps> = (
62
- props
63
- ) => {
58
+ export const AzureProvider: React.FC<IAzureProviderProps> = (props) => {
64
59
  const startedRef = React.useRef<boolean>(false);
65
60
  const clientRef = React.useRef<AzureTurboClient>(
66
61
  new AzureTurboClient(props.clientOptions)
@@ -5,18 +5,44 @@
5
5
 
6
6
  import { IFluidContainer, LoadableObjectClassRecord } from "fluid-framework";
7
7
  import React from "react";
8
- import { ILiveShareContainerResults } from "../types";
9
8
  import { useSharedStateRegistry } from "../internal-hooks";
10
- import { ILiveShareClientOptions, ILiveShareHost } from "@microsoft/live-share";
9
+ import {
10
+ ILiveShareClientOptions,
11
+ ILiveShareHost,
12
+ ILiveShareJoinResults,
13
+ ITimestampProvider,
14
+ } from "@microsoft/live-share";
11
15
  import { FluidContext } from "./AzureProvider";
12
16
  import { LiveShareTurboClient } from "@microsoft/live-share-turbo";
13
17
 
14
- interface ILiveShareContext {
15
- created: boolean | undefined;
18
+ export interface ILiveShareContext {
19
+ /**
20
+ * True if the local user created the Fluid container
21
+ */
22
+ created: boolean;
23
+ /**
24
+ * True if connected to the Live Share container
25
+ */
26
+ joined: boolean;
27
+ /**
28
+ * An error that will be defined if there was a problem joining the container, or undefined if not.
29
+ */
30
+ joinError: Error | undefined;
31
+ /**
32
+ * Live Share timestamp provider. Can be used to `.getTimestamp()` for a global clock value.
33
+ * This reference timestamp value should be fairly consistent for all users in the session.
34
+ */
35
+ timestampProvider: ITimestampProvider | undefined;
36
+ /**
37
+ * Join callback method
38
+ * @param initialObjects Optional. The initial objects for the Fluid container schema.
39
+ * @param onInitializeContainer Optional. Callback for when the container is first created.
40
+ * @returns `ILiveShareJoinResults`, which includes the Fluid container
41
+ */
16
42
  join: (
17
43
  initialObjects?: LoadableObjectClassRecord,
18
44
  onInitializeContainer?: (container: IFluidContainer) => void
19
- ) => Promise<ILiveShareContainerResults>;
45
+ ) => Promise<ILiveShareJoinResults>;
20
46
  }
21
47
 
22
48
  export const LiveShareContext = React.createContext<ILiveShareContext>(
@@ -54,15 +80,13 @@ interface ILiveShareProviderProps {
54
80
  /**
55
81
  * React Context provider component for using Live Share data objects & joining a Live Share session using `LiveShareClient`.
56
82
  */
57
- export const LiveShareProvider: React.FC<
58
- ILiveShareProviderProps
59
- > = (props) => {
83
+ export const LiveShareProvider: React.FC<ILiveShareProviderProps> = (props) => {
60
84
  const startedRef = React.useRef(false);
61
85
  const clientRef = React.useRef(
62
86
  new LiveShareTurboClient(props.host, props.clientOptions)
63
87
  );
64
88
  const [results, setResults] = React.useState<
65
- ILiveShareContainerResults | undefined
89
+ ILiveShareJoinResults | undefined
66
90
  >();
67
91
  const [joinError, setJoinError] = React.useState<Error | undefined>();
68
92
 
@@ -75,10 +99,12 @@ export const LiveShareProvider: React.FC<
75
99
  async (
76
100
  initialObjects?: LoadableObjectClassRecord,
77
101
  onInitializeContainer?: (container: IFluidContainer) => void
78
- ): Promise<ILiveShareContainerResults> => {
102
+ ): Promise<ILiveShareJoinResults> => {
79
103
  startedRef.current = true;
80
- const results: ILiveShareContainerResults =
81
- await clientRef.current.join(initialObjects, onInitializeContainer);
104
+ const results = await clientRef.current.join(
105
+ initialObjects,
106
+ onInitializeContainer
107
+ );
82
108
  setResults(results);
83
109
  return results;
84
110
  },
@@ -92,9 +118,10 @@ export const LiveShareProvider: React.FC<
92
118
  // This hook should only be called once, so we use a ref to track if it has been called.
93
119
  // This is a workaround for the fact that useEffect is called twice on initial render in React V18.
94
120
  // We are not doing this here for backwards compatibility. View the README for more information.
95
- if (results !== undefined || startedRef.current || !props.joinOnLoad) return;
121
+ if (results !== undefined || startedRef.current || !props.joinOnLoad)
122
+ return;
96
123
  join(props.initialObjects).catch((error) => {
97
- console.log(error);
124
+ console.error(error);
98
125
  if (error instanceof Error) {
99
126
  setJoinError(error);
100
127
  } else {
@@ -110,7 +137,10 @@ export const LiveShareProvider: React.FC<
110
137
  return (
111
138
  <LiveShareContext.Provider
112
139
  value={{
113
- created: results?.created,
140
+ created: !!results?.created,
141
+ timestampProvider: results?.timestampProvider,
142
+ joined: !!results?.container,
143
+ joinError,
114
144
  join,
115
145
  }}
116
146
  >
@@ -16,10 +16,12 @@ import { LoadableObjectClass } from "fluid-framework";
16
16
  * @param onFirstInitialize Optional. Callback function for when the DDS is first loaded
17
17
  * @returns the DDS object, which is of type T when loaded and undefined while loading
18
18
  */
19
- export function useDynamicDDS<T extends IFluidLoadable = FluidObject<any> & IFluidLoadable>(
19
+ export function useDynamicDDS<
20
+ T extends IFluidLoadable = FluidObject<any> & IFluidLoadable
21
+ >(
20
22
  uniqueKey: string,
21
23
  loadableObjectClass: LoadableObjectClass<T>,
22
- onFirstInitialize?: (dds: T) => void,
24
+ onFirstInitialize?: (dds: T) => void
23
25
  ): {
24
26
  dds: T | undefined;
25
27
  error: Error | undefined;
@@ -29,10 +31,7 @@ export function useDynamicDDS<T extends IFluidLoadable = FluidObject<any> & IFlu
29
31
  /**
30
32
  * Import container and DDS object register callbacks from AzureProvider.
31
33
  */
32
- const {
33
- container,
34
- clientRef,
35
- } = useFluidObjectsContext();
34
+ const { container, clientRef } = useFluidObjectsContext();
36
35
 
37
36
  /**
38
37
  * Once container is available, this effect will register the setter method so that the DDS loaded
@@ -46,7 +45,11 @@ export function useDynamicDDS<T extends IFluidLoadable = FluidObject<any> & IFlu
46
45
  // Callback method to set the `initialData` into the map when the DDS is first created.
47
46
  const onGetDDS = async () => {
48
47
  try {
49
- const dds = await clientRef.current.getDDS<T>(uniqueKey, loadableObjectClass, onFirstInitialize);
48
+ const dds = await clientRef.current.getDDS<T>(
49
+ uniqueKey,
50
+ loadableObjectClass,
51
+ onFirstInitialize
52
+ );
50
53
  if (mounted) {
51
54
  setDDS(dds);
52
55
  }
@@ -54,7 +57,11 @@ export function useDynamicDDS<T extends IFluidLoadable = FluidObject<any> & IFlu
54
57
  if (error instanceof Error) {
55
58
  setError(error);
56
59
  } else {
57
- setError(new Error("useDynamicDDS: an unknown error occurred while getting the DDS"));
60
+ setError(
61
+ new Error(
62
+ "useDynamicDDS: an unknown error occurred while getting the DDS"
63
+ )
64
+ );
58
65
  }
59
66
  }
60
67
  };
@@ -35,19 +35,26 @@ export function useSharedMap<TData extends object = object>(
35
35
  getInitialData<TData>(initialData)
36
36
  );
37
37
 
38
- const onFirstInitialize = React.useCallback((newDDS: SharedMap): void => {
39
- /**
40
- * Callback method to set the `initialData` into the map when the `SharedMap` is first created.
41
- * Only should be used as a prop to useDynamicDDS.
42
- */
43
- getInitialData(initialData).forEach((value, key) => {
44
- newDDS.set(key, value);
45
- });
46
- }, [initialData]);
38
+ const onFirstInitialize = React.useCallback(
39
+ (newDDS: SharedMap): void => {
40
+ /**
41
+ * Callback method to set the `initialData` into the map when the `SharedMap` is first created.
42
+ * Only should be used as a prop to useDynamicDDS.
43
+ */
44
+ getInitialData(initialData).forEach((value, key) => {
45
+ newDDS.set(key, value);
46
+ });
47
+ },
48
+ [initialData]
49
+ );
47
50
  /**
48
51
  * User facing: dynamically load the SharedMap DDS for the given unique key.
49
52
  */
50
- const { dds: sharedMap } = useDynamicDDS<SharedMap>(uniqueKey, SharedMap, onFirstInitialize);
53
+ const { dds: sharedMap } = useDynamicDDS<SharedMap>(
54
+ uniqueKey,
55
+ SharedMap,
56
+ onFirstInitialize
57
+ );
51
58
 
52
59
  /**
53
60
  * User facing: set a value to the Fluid `SharedMap`.
@@ -79,7 +79,11 @@ export function useSharedState<S>(
79
79
  return () => {
80
80
  unregisterSharedSetStateAction(uniqueKey, componentIdRef.current);
81
81
  };
82
- }, [uniqueKey, registerSharedSetStateAction, unregisterSharedSetStateAction]);
82
+ }, [
83
+ uniqueKey,
84
+ registerSharedSetStateAction,
85
+ unregisterSharedSetStateAction,
86
+ ]);
83
87
 
84
88
  return [localState, setSharedState, disposeSharedState];
85
89
  }
@@ -6,13 +6,19 @@
6
6
  import React from "react";
7
7
  import { IFluidLoadable } from "@fluidframework/core-interfaces";
8
8
  import { LoadableObjectClass } from "fluid-framework";
9
- import { ITimerConfig, PresenceState } from "@microsoft/live-share";
9
+ import { ITimerConfig, ILiveEvent, PresenceState } from "@microsoft/live-share";
10
10
 
11
11
  // React actions
12
+
12
13
  export type SetSharedStateAction<T> = (state: T) => void;
13
14
  export type SetLocalStateAction = React.Dispatch<React.SetStateAction<any>>;
14
15
 
15
16
  // Fluid actions
17
+
18
+ /**
19
+ * Callback for UnregisterDDSSetStateAction.
20
+ * <T extends IFluidLoadable>(uniqueKey: string, componentId: string, objectClass: LoadableObjectClass<T>, setLocalStateAction: SetLocalStateAction, onDidFirstInitialize?: (dds: T) => void) => void
21
+ */
16
22
  export type RegisterDDSSetStateAction = <T extends IFluidLoadable>(
17
23
  uniqueKey: string,
18
24
  componentId: string,
@@ -21,55 +27,127 @@ export type RegisterDDSSetStateAction = <T extends IFluidLoadable>(
21
27
  onDidFirstInitialize?: (dds: T) => void
22
28
  ) => void;
23
29
 
30
+ /**
31
+ * Callback for UnregisterDDSSetStateAction.
32
+ * (uniqueKey: string, componentId: string) => void
33
+ */
24
34
  export type UnregisterDDSSetStateAction = (
25
35
  uniqueKey: string,
26
36
  componentId: string
27
37
  ) => void;
28
38
 
39
+ /**
40
+ * Callback for RegisterSharedSetStateAction.
41
+ * (uniqueKey: string, componentId: string, setLocalStateAction: SetLocalStateAction) => void
42
+ */
29
43
  export type RegisterSharedSetStateAction = (
30
44
  uniqueKey: string,
31
45
  componentId: string,
32
46
  setLocalStateAction: SetLocalStateAction
33
47
  ) => void;
34
48
 
49
+ /**
50
+ * Callback for UnregisterSharedSetStateAction.
51
+ * (uniqueKey: string, componentId: string) => void
52
+ */
35
53
  export type UnregisterSharedSetStateAction = (
36
54
  uniqueKey: string,
37
55
  componentId: string
38
56
  ) => void;
39
57
 
58
+ /**
59
+ * Callback for UpdateSharedStateAction.
60
+ * (uniqueKey: string, value: any) => void
61
+ */
40
62
  export type UpdateSharedStateAction = (uniqueKey: string, value: any) => void;
41
63
 
64
+ /**
65
+ * Callback for DeleteSharedStateAction.
66
+ * (uniqueKey: string) => void
67
+ */
42
68
  export type DeleteSharedStateAction = (uniqueKey: string) => void;
69
+ /**
70
+ * Callback for DisposeSharedStateAction.
71
+ * () => void
72
+ */
43
73
  export type DisposeSharedStateAction = () => void;
44
74
 
45
75
  // Live Share actions
46
76
 
77
+ /**
78
+ * Callback for SetLiveStateAction<TState = undefined>.
79
+ * (state: TState) => Promise<void>
80
+ */
47
81
  export type SetLiveStateAction<TState = undefined> = (
48
- state: TState,
49
- ) => void;
82
+ state: TState
83
+ ) => Promise<void>;
50
84
 
51
- export type SendLiveEventAction<TEvent> = (event: TEvent) => void;
85
+ /**
86
+ * Callback for SendLiveEventAction<TEvent>.
87
+ * (event: TEvent) => Promise<void>
88
+ */
89
+ export type SendLiveEventAction<TEvent> = (
90
+ event: TEvent
91
+ ) => Promise<ILiveEvent<TEvent>>;
52
92
 
93
+ /**
94
+ * Callback for OnReceivedLiveEventAction<TEvent>.
95
+ * (event: TEvent, local: boolean) => void
96
+ */
53
97
  export type OnReceivedLiveEventAction<TEvent> = (
54
98
  event: TEvent,
55
99
  local: boolean
56
100
  ) => void;
57
101
 
102
+ /**
103
+ * Callback for OnUpdateLivePresenceAction<TData extends object = object>.
104
+ * (data?: TData | undefined, state?: PresenceState | undefined) => Promise<void>
105
+ */
58
106
  export type OnUpdateLivePresenceAction<TData extends object = object> = (
59
107
  data?: TData | undefined,
60
- state?: PresenceState | undefined,
61
- ) => void;
108
+ state?: PresenceState | undefined
109
+ ) => Promise<void>;
62
110
 
63
- export type OnStartTimerAction = (
64
- duration: number
65
- ) => void;
111
+ /**
112
+ * Callback for OnStartTimerAction.
113
+ * (duration: number) => Promise<void>
114
+ */
115
+ export type OnStartTimerAction = (duration: number) => Promise<void>;
66
116
 
67
- export type OnPlayTimerAction = () => void;
117
+ /**
118
+ * Callback for OnPlayTimerAction.
119
+ * () => Promise<void>
120
+ */
121
+ export type OnPlayTimerAction = () => Promise<void>;
68
122
 
69
- export type OnPauseTimerAction = () => void;
123
+ /**
124
+ * Callback for OnPauseTimerAction.
125
+ * () => Promise<void>
126
+ */
127
+ export type OnPauseTimerAction = () => Promise<void>;
70
128
 
129
+ /**
130
+ * Callback for OnTimerTickAction.
131
+ * (milliRemaining: number) => void
132
+ */
71
133
  export type OnTimerTickAction = (milliRemaining: number) => void;
134
+ /**
135
+ * Callback for OnTimerDidStartAction.
136
+ * (timerConfig: ITimerConfig) => void
137
+ */
72
138
  export type OnTimerDidStartAction = (timerConfig: ITimerConfig) => void;
139
+ /**
140
+ * Callback for OnTimerDidPauseAction.
141
+ * (timerConfig: ITimerConfig) => void
142
+ */
73
143
  export type OnTimerDidPauseAction = (timerConfig: ITimerConfig) => void;
144
+ /**
145
+ * Callback for OnTimerDidPlayAction.
146
+ * (timerConfig: ITimerConfig) => void
147
+ */
74
148
  export type OnTimerDidPlayAction = (timerConfig: ITimerConfig) => void;
149
+ /**
150
+ * Callback for OnTimerDidFinishAction.
151
+ * (timerConfig: ITimerConfig) => void
152
+ */
75
153
  export type OnTimerDidFinishAction = (timerConfig: ITimerConfig) => void;