@aperture-browser/session-react 0.0.0-nightly.82.2e4f6368108f → 0.0.0-nightly.84.0c72bc0d2eaf

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.
@@ -8,6 +8,7 @@ import * as Schema from "effect/Schema";
8
8
  import * as SubscriptionRef from "effect/SubscriptionRef";
9
9
  import * as Data from "effect/Data";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
+ import * as Redacted from "effect/Redacted";
11
12
  import { SessionsApi, apiClientLayer, baseUrlLayer } from "@aperture-browser/api-client";
12
13
  import * as Layer from "effect/Layer";
13
14
  import * as ManagedRuntime from "effect/ManagedRuntime";
@@ -94,7 +95,7 @@ const pointerButtonCode = {
94
95
  right: 273,
95
96
  middle: 274
96
97
  };
97
- function useLiveSession({ sessionId, displayName = null, credentials, sessionToken, role, enabled, webrtcSupported, iceServers }) {
98
+ function useLiveSession({ sessionId, displayName = null, credentials, sessionToken, role, enabled, webrtcSupported, iceServers, autoSize }) {
98
99
  const identity = useMemo(() => collaborationIdentity(role, displayName), [displayName, role]);
99
100
  const runtime = useRuntime();
100
101
  const baseUrl = useBaseUrl();
@@ -127,6 +128,7 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
127
128
  const [presentationSwitching, setPresentationSwitching] = useState(false);
128
129
  const [presentation, setPresentation] = useState(null);
129
130
  const [recordings, setRecordings] = useState([]);
131
+ const [viewportOwnership, setViewportOwnership] = useState(null);
130
132
  const [clientId, setClientId] = useState("");
131
133
  const [holderClientId, setHolderClientId] = useState(null);
132
134
  const [leaseMode, setLeaseMode] = useState(null);
@@ -152,6 +154,10 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
152
154
  setMediaSize(resolveMediaSize(message.targets, message.activeTargetId));
153
155
  setRecordings(message.recordings);
154
156
  setPresentation(message.presentation ?? null);
157
+ setViewportOwnership(message.autoSize === void 0 ? null : {
158
+ ownerClientId: message.viewportOwnerClientId ?? null,
159
+ autoSize: message.autoSize
160
+ });
155
161
  setLastError(null);
156
162
  return;
157
163
  case "targets.state":
@@ -179,6 +185,12 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
179
185
  releasePendingRef.current = false;
180
186
  setLastError((current) => current?.code === "input_busy" || current?.code === "input_not_owned" ? null : current);
181
187
  return;
188
+ case "viewport.state":
189
+ setViewportOwnership({
190
+ ownerClientId: message.viewportOwnerClientId ?? null,
191
+ autoSize: message.autoSize
192
+ });
193
+ return;
182
194
  case "presence.cursor":
183
195
  if (message.clientId !== followingClientIdRef.current) return;
184
196
  setCursors((current) => new Map(current).set(message.clientId, message));
@@ -234,6 +246,7 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
234
246
  setParticipants([]);
235
247
  setCursors(/* @__PURE__ */ new Map());
236
248
  setRecordings([]);
249
+ setViewportOwnership(null);
237
250
  publishFrame(null);
238
251
  publishPaint({ type: "clear" });
239
252
  return;
@@ -245,6 +258,7 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
245
258
  credentials,
246
259
  sessionToken,
247
260
  identity,
261
+ autoSize,
248
262
  iceServers,
249
263
  webrtcSupported,
250
264
  callbacks: {
@@ -269,6 +283,7 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
269
283
  publishPaint({ type: "clear" });
270
284
  })));
271
285
  }, [
286
+ autoSize,
272
287
  baseUrl,
273
288
  credentials,
274
289
  enabled,
@@ -525,6 +540,7 @@ function useLiveSession({ sessionId, displayName = null, credentials, sessionTok
525
540
  presentation,
526
541
  mediaSwitching: targetSwitching || presentationSwitching,
527
542
  recordings,
543
+ viewportOwnership,
528
544
  sendBrowserInput,
529
545
  selectTarget,
530
546
  requestSelectTarget,
@@ -1749,6 +1765,7 @@ function focusedElement(node) {
1749
1765
  //#endregion
1750
1766
  //#region src/hooks/use-browser-control.ts
1751
1767
  const emptyIceServers$1 = [];
1768
+ const AUTO_SIZE_DEFAULT_STORAGE_KEY = "aperture.viewport.auto-size-default";
1752
1769
  function useBrowserControl({ sessionId, credentials, displayName, sessionToken, collaborationRole = "owner", enabled = true, webrtcProducerSupported = false, webrtcIceServers = emptyIceServers$1, onNotice }) {
1753
1770
  const runtime = useRuntime();
1754
1771
  const onNoticeRef = useRef(onNotice);
@@ -1757,6 +1774,11 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1757
1774
  level,
1758
1775
  message
1759
1776
  }));
1777
+ const [viewportAutoSizeDefault, setViewportAutoSizeDefaultState] = useState(loadAutoSizeDefault);
1778
+ const [viewportAutoSync, setViewportAutoSyncState] = useState(() => collaborationRole !== "viewer" && viewportAutoSizeDefault);
1779
+ const viewportAutoSyncRef = useRef(viewportAutoSync);
1780
+ viewportAutoSyncRef.current = viewportAutoSync;
1781
+ const autoSizePreference = useCallback(() => viewportAutoSyncRef.current, []);
1760
1782
  const live = useLiveSession({
1761
1783
  sessionId,
1762
1784
  displayName,
@@ -1765,7 +1787,8 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1765
1787
  role: collaborationRole,
1766
1788
  enabled: Boolean(enabled && sessionId && credentials),
1767
1789
  webrtcSupported: webrtcProducerSupported,
1768
- iceServers: webrtcIceServers
1790
+ iceServers: webrtcIceServers,
1791
+ autoSize: autoSizePreference
1769
1792
  });
1770
1793
  const [targetOrder, setTargetOrder] = useState([]);
1771
1794
  const targets = useMemo(() => mergeTargetsInCurrentOrder(targetOrder, live.targets), [live.targets, targetOrder]);
@@ -1775,18 +1798,15 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1775
1798
  phaseRef.current = live.phase;
1776
1799
  const [viewport, setViewportState] = useState(DEFAULT_VIEWPORT);
1777
1800
  const [browserViewportSize, setBrowserViewportSizeState] = useState(null);
1778
- const [viewportAutoSync, setViewportAutoSyncState] = useState(false);
1779
1801
  const [captured, setCaptured] = useState(false);
1780
1802
  const [recordingBusy, setRecordingBusy] = useState(false);
1781
1803
  const activeTargetIdRef = useRef(null);
1782
1804
  const viewportRef = useRef(viewport);
1783
1805
  const inputDimensionsRef = useRef(DEFAULT_VIEWPORT);
1784
1806
  const browserViewportSizeRef = useRef(null);
1785
- const viewportAutoSyncRef = useRef(false);
1786
1807
  activeTargetIdRef.current = live.activeTargetId;
1787
1808
  viewportRef.current = viewport;
1788
1809
  browserViewportSizeRef.current = browserViewportSize;
1789
- viewportAutoSyncRef.current = viewportAutoSync;
1790
1810
  useEffect(() => {
1791
1811
  if (live.phase !== "connected") setCaptured(false);
1792
1812
  }, [live.phase]);
@@ -1859,21 +1879,54 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1859
1879
  const targetId = activeTargetIdRef.current;
1860
1880
  if (targetId) live.command("page.history-forward", { targetId });
1861
1881
  }, [live]);
1862
- const commitViewport = useCallback((preset) => {
1882
+ const viewportOwnership = live.viewportOwnership;
1883
+ const viewportOwnershipRef = useRef(viewportOwnership);
1884
+ viewportOwnershipRef.current = viewportOwnership;
1885
+ const viewportAutoSizeActive = viewportAutoSync && (viewportOwnership === null || viewportOwnership.ownerClientId === live.collaboration.clientId);
1886
+ const viewportAutoSizeActiveRef = useRef(viewportAutoSizeActive);
1887
+ viewportAutoSizeActiveRef.current = viewportAutoSizeActive;
1888
+ useEffect(() => {
1889
+ if (viewportOwnership !== null) {
1890
+ viewportAutoSyncRef.current = viewportOwnership.autoSize;
1891
+ setViewportAutoSyncState(viewportOwnership.autoSize);
1892
+ }
1893
+ }, [viewportOwnership]);
1894
+ const runAutoSizeViewport = useEffectCallback((payload) => live.request("viewport.set", payload).pipe(Effect.ignore), [live.request]);
1895
+ const commitViewport = useCallback((preset, autoSize) => {
1863
1896
  setViewportState(preset);
1864
1897
  const targetId = activeTargetIdRef.current;
1865
- if (targetId) live.command("viewport.set", {
1898
+ if (targetId === null) return;
1899
+ const payload = {
1866
1900
  targetId,
1867
1901
  width: preset.width,
1868
1902
  height: preset.height,
1869
1903
  deviceScaleFactor: preset.deviceScaleFactor
1904
+ };
1905
+ if (autoSize && viewportOwnershipRef.current !== null) runAutoSizeViewport({
1906
+ ...payload,
1907
+ autoSize: true
1870
1908
  });
1871
- }, [live]);
1909
+ else live.command("viewport.set", payload);
1910
+ }, [live.command, runAutoSizeViewport]);
1911
+ const setViewportAutoSync = useCallback((nextEnabled) => {
1912
+ if (viewportAutoSyncRef.current === nextEnabled) return;
1913
+ viewportAutoSyncRef.current = nextEnabled;
1914
+ setViewportAutoSyncState(nextEnabled);
1915
+ if (viewportOwnershipRef.current !== null) live.command("viewport.auto-size.set", { enabled: nextEnabled });
1916
+ }, [live.command]);
1917
+ useEffect(() => {
1918
+ const size = browserViewportSizeRef.current;
1919
+ if (viewportAutoSizeActive && live.phase === "connected" && live.activeTargetId !== null && size !== null) commitViewport(createBrowserViewport(size, viewportRef.current.deviceScaleFactor), true);
1920
+ }, [
1921
+ commitViewport,
1922
+ live.activeTargetId,
1923
+ live.phase,
1924
+ viewportAutoSizeActive
1925
+ ]);
1872
1926
  const setViewport = useCallback((preset) => {
1873
- viewportAutoSyncRef.current = false;
1874
- setViewportAutoSyncState(false);
1875
- commitViewport(preset);
1876
- }, [commitViewport]);
1927
+ setViewportAutoSync(false);
1928
+ commitViewport(preset, false);
1929
+ }, [commitViewport, setViewportAutoSync]);
1877
1930
  const setBrowserViewportSize = useCallback((size) => {
1878
1931
  const next = {
1879
1932
  width: Math.round(size.width),
@@ -1884,21 +1937,25 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1884
1937
  if (current?.width === next.width && current.height === next.height) return;
1885
1938
  browserViewportSizeRef.current = next;
1886
1939
  setBrowserViewportSizeState(next);
1887
- if (viewportAutoSyncRef.current) commitViewport(createBrowserViewport(next, viewportRef.current.deviceScaleFactor));
1888
- }, [commitViewport]);
1889
- const setViewportAutoSync = useCallback((nextEnabled) => {
1890
- viewportAutoSyncRef.current = nextEnabled;
1891
- setViewportAutoSyncState(nextEnabled);
1892
- const size = browserViewportSizeRef.current;
1893
- if (nextEnabled && size) commitViewport(createBrowserViewport(size, viewportRef.current.deviceScaleFactor));
1940
+ if (viewportAutoSizeActiveRef.current) commitViewport(createBrowserViewport(next, viewportRef.current.deviceScaleFactor), true);
1894
1941
  }, [commitViewport]);
1895
1942
  const setViewportToBrowserSize = useCallback(() => {
1896
1943
  const size = browserViewportSizeRef.current;
1897
1944
  if (!size) return;
1898
- viewportAutoSyncRef.current = false;
1899
- setViewportAutoSyncState(false);
1900
- commitViewport(createBrowserViewport(size, viewportRef.current.deviceScaleFactor));
1901
- }, [commitViewport]);
1945
+ setViewportAutoSync(false);
1946
+ commitViewport(createBrowserViewport(size, viewportRef.current.deviceScaleFactor), false);
1947
+ }, [commitViewport, setViewportAutoSync]);
1948
+ const takeOverViewport = useCallback(() => {
1949
+ viewportAutoSyncRef.current = true;
1950
+ setViewportAutoSyncState(true);
1951
+ live.command("viewport.owner.claim");
1952
+ }, [live.command]);
1953
+ const setViewportAutoSizeDefault = useCallback((nextEnabled) => {
1954
+ setViewportAutoSizeDefaultState(nextEnabled);
1955
+ try {
1956
+ window.localStorage.setItem(AUTO_SIZE_DEFAULT_STORAGE_KEY, String(nextEnabled));
1957
+ } catch {}
1958
+ }, []);
1902
1959
  const settleRecording = (effect, failure) => effect.pipe(Effect.catch((error) => notify("error", errorMessage(error, failure))), Effect.ensuring(Effect.sync(() => setRecordingBusy(false))));
1903
1960
  const runStartRecording = useEffectCallback((mode, targetId) => settleRecording(live.request("recording.start", {
1904
1961
  mode,
@@ -1914,7 +1971,7 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1914
1971
  recordingBusy,
1915
1972
  runStartRecording
1916
1973
  ]);
1917
- const runStopRecording = useEffectCallback((credentials, sessionId, recordingId) => settleRecording(live.request("recording.stop", { recordingId }).pipe(Effect.andThen(SessionsApi.use((sessions) => sessions.downloadSessionRecording(credentials, sessionId, recordingId, sessionToken))), Effect.flatMap(({ blob, filename }) => {
1974
+ const runStopRecording = useEffectCallback((credentials, sessionId, recordingId) => settleRecording(live.request("recording.stop", { recordingId }).pipe(Effect.andThen(SessionsApi.use((sessions) => sessions.downloadSessionRecording(credentials, sessionId, recordingId, sessionToken === void 0 ? void 0 : Redacted.make(sessionToken)))), Effect.flatMap(({ blob, filename }) => {
1918
1975
  const recording = live.recordings.find((candidate) => candidate.recordingId === recordingId);
1919
1976
  return downloadBlob(blob, filename ?? `${sessionId}-${recording?.targetId ?? "target"}-${recordingId}.webm`);
1920
1977
  }), Effect.andThen(notify("success", "Recording saved"))), "Recording failed to stop"), [live, sessionToken]);
@@ -1999,6 +2056,9 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
1999
2056
  viewport,
2000
2057
  browserViewportSize,
2001
2058
  viewportAutoSync,
2059
+ viewportAutoSizeActive,
2060
+ viewportOwnership,
2061
+ viewportAutoSizeDefault,
2002
2062
  captured,
2003
2063
  recordings: live.recordings,
2004
2064
  recordingBusy,
@@ -2013,6 +2073,8 @@ function useBrowserControl({ sessionId, credentials, displayName, sessionToken,
2013
2073
  setBrowserViewportSize,
2014
2074
  setViewportAutoSync,
2015
2075
  setViewportToBrowserSize,
2076
+ setViewportAutoSizeDefault,
2077
+ takeOverViewport,
2016
2078
  setWebRTCStreamSettings,
2017
2079
  selectMediaStream,
2018
2080
  sendInput,
@@ -2047,6 +2109,13 @@ function mergeTargetsInCurrentOrder(order, nextTargets) {
2047
2109
  for (const nextTarget of nextTargets) if (!seen.has(nextTarget.id)) ordered.push(nextTarget);
2048
2110
  return ordered;
2049
2111
  }
2112
+ function loadAutoSizeDefault() {
2113
+ try {
2114
+ return window.localStorage.getItem(AUTO_SIZE_DEFAULT_STORAGE_KEY) === "true";
2115
+ } catch {
2116
+ return false;
2117
+ }
2118
+ }
2050
2119
  function createBrowserViewport(size, deviceScaleFactor) {
2051
2120
  return createViewportPreset(size.width, size.height, deviceScaleFactor);
2052
2121
  }
@@ -2097,7 +2166,7 @@ function useSharedSession({ token, displayName, onNotice }) {
2097
2166
  const share = useMemo(() => parseShareToken(token), [token]);
2098
2167
  const credentials = useMemo(() => share && {
2099
2168
  kind: "bearer",
2100
- token: share.token,
2169
+ token: Redacted.make(share.token),
2101
2170
  authorityType: null,
2102
2171
  tenantId: null,
2103
2172
  selectedTenantId: null
@@ -2132,4 +2201,4 @@ function useSharedSession({ token, displayName, onNotice }) {
2132
2201
  //#endregion
2133
2202
  export { makeApertureRuntime as a, collaborationPaintLifetimeMs as c, RuntimeProviderMissingError as d, useBaseUrl as f, useRuntime as g, useRunApi as h, ApertureProvider as i, useLiveSession as l, useFork as m, parseShareToken as n, useBrowserControl as o, useEffectCallback as p, useSharedSession as r, SessionViewport as s, LiveSessionError$1 as t, RuntimeProvider as u };
2134
2203
 
2135
- //# sourceMappingURL=headless-CKFacFX3.js.map
2204
+ //# sourceMappingURL=headless-CJ5KaGbF.js.map