@q9labsai/chalk-react-native 5.1.0 → 5.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/{chunk-4L5GXJ36.js → chunk-BXDD5BE4.js} +23 -1
- package/dist/{chunk-MBZRE4US.js → chunk-PPQSOU35.js} +5 -5
- package/dist/client.js +1 -0
- package/dist/components/EmbeddedWhiteboard.d.ts +8 -4
- package/dist/frame/call-controls.d.ts +2 -0
- package/dist/frame/use-landscape-chrome.d.ts +8 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +358 -97
- package/dist/invites.d.ts +5 -0
- package/dist/invites.js +3 -1
- package/dist/primitives/IconButton.d.ts +1 -0
- package/dist/primitives/NameTag.d.ts +2 -1
- package/dist/primitives/TileShell.d.ts +2 -1
- package/dist/stage/ParticipantTile.d.ts +3 -1
- package/dist/stage/TileSheet.d.ts +1 -1
- package/dist/stage/stage-view.d.ts +4 -0
- package/dist/ui.js +1 -1
- package/dist/whiteboard/export-board-image.d.ts +6 -0
- package/dist/whiteboard/native-board-session.d.ts +15 -0
- package/embedded/chalk-whiteboard/Figtree-Regular.ttf +0 -0
- package/embedded/chalk-whiteboard/Figtree-SemiBold.ttf +0 -0
- package/embedded/chalk-whiteboard/asset-manifest.json +19 -4
- package/embedded/chalk-whiteboard/chalk.css +44 -0
- package/embedded/chalk-whiteboard/licenses/Figtree.txt +93 -0
- package/embedded/chalk-whiteboard/renderer.js +1669 -1418
- package/package.json +11 -6
- package/src/components/EmbeddedWhiteboard.tsx +90 -6
- package/src/dock/Dock.tsx +14 -3
- package/src/dock/MoreSheet.tsx +23 -0
- package/src/frame/CallFrame.tsx +20 -33
- package/src/frame/call-controls.ts +4 -0
- package/src/frame/use-landscape-chrome.ts +22 -0
- package/src/index.ts +2 -2
- package/src/invites.ts +32 -1
- package/src/primitives/IconButton.tsx +6 -5
- package/src/primitives/NameTag.tsx +7 -1
- package/src/primitives/TileShell.tsx +3 -1
- package/src/space-client/create-native-space-client.ts +1 -0
- package/src/stage/ContentTile.tsx +64 -19
- package/src/stage/ParticipantTile.tsx +6 -4
- package/src/stage/Stage.tsx +37 -6
- package/src/stage/TileSheet.tsx +17 -2
- package/src/stage/stage-view.tsx +11 -1
- package/src/whiteboard/export-board-image.ts +21 -0
- package/src/whiteboard/native-board-session.ts +29 -0
package/dist/index.js
CHANGED
|
@@ -4,8 +4,9 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
extractSpaceInviteFromLink,
|
|
6
6
|
getClipboardInviteSuggestion,
|
|
7
|
+
parseChalkInviteLink,
|
|
7
8
|
parseSpaceInviteLink
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BXDD5BE4.js";
|
|
9
10
|
import {
|
|
10
11
|
BottomSheet,
|
|
11
12
|
ChalkText,
|
|
@@ -53,13 +54,13 @@ import {
|
|
|
53
54
|
useTheme,
|
|
54
55
|
useToasts,
|
|
55
56
|
viewer
|
|
56
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-PPQSOU35.js";
|
|
57
58
|
import {
|
|
58
59
|
useMeasuredRef
|
|
59
60
|
} from "./chunk-GYVZSOGQ.js";
|
|
60
61
|
|
|
61
62
|
// src/frame/Chalk.tsx
|
|
62
|
-
import { useEffect as
|
|
63
|
+
import { useEffect as useEffect23 } from "react";
|
|
63
64
|
import { StyleSheet as StyleSheet24 } from "react-native";
|
|
64
65
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
65
66
|
import { SafeAreaProvider as SafeAreaProvider2 } from "react-native-safe-area-context";
|
|
@@ -114,6 +115,8 @@ var StageViewContext = createContext2(null);
|
|
|
114
115
|
function StageViewProvider({ children }) {
|
|
115
116
|
const [layout, setLayout] = useState("spotlight");
|
|
116
117
|
const [pinned, setPinned] = useState(null);
|
|
118
|
+
const [boardOpen, setBoardOpen] = useState(null);
|
|
119
|
+
const [following, setFollowing] = useState(null);
|
|
117
120
|
const [mirror, setMirror] = useState(true);
|
|
118
121
|
const dev = useDevScenario();
|
|
119
122
|
useEffect(() => {
|
|
@@ -124,6 +127,10 @@ function StageViewProvider({ children }) {
|
|
|
124
127
|
() => ({
|
|
125
128
|
layout,
|
|
126
129
|
pinned,
|
|
130
|
+
boardOpen,
|
|
131
|
+
setBoardOpen,
|
|
132
|
+
following,
|
|
133
|
+
setFollowing,
|
|
127
134
|
mirror,
|
|
128
135
|
setLayout: (next) => {
|
|
129
136
|
setLayout(next);
|
|
@@ -143,7 +150,7 @@ function StageViewProvider({ children }) {
|
|
|
143
150
|
},
|
|
144
151
|
setMirror
|
|
145
152
|
}),
|
|
146
|
-
[layout, mirror, pinned]
|
|
153
|
+
[layout, mirror, pinned, following, boardOpen]
|
|
147
154
|
);
|
|
148
155
|
return /* @__PURE__ */ jsx2(StageViewContext.Provider, { value, children });
|
|
149
156
|
}
|
|
@@ -154,7 +161,7 @@ function useStageView() {
|
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
// src/frame/CallFrame.tsx
|
|
157
|
-
import { useCallback as
|
|
164
|
+
import { useCallback as useCallback17, useEffect as useEffect22, useMemo as useMemo12, useRef as useRef13, useState as useState15 } from "react";
|
|
158
165
|
import { Pressable as Pressable15, StatusBar, StyleSheet as StyleSheet23, View as View22 } from "react-native";
|
|
159
166
|
import Animated12, { useAnimatedStyle as useAnimatedStyle7, useSharedValue as useSharedValue5, withTiming as withTiming7 } from "react-native-reanimated";
|
|
160
167
|
|
|
@@ -295,13 +302,27 @@ function RoutePicker({ open, onClose, onSelect, output, anchorRef }) {
|
|
|
295
302
|
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
296
303
|
var Dock = memo(function Dock2({ arrangement, microphoneOn, cameraOn, onToggleMicrophone, onToggleCamera, onOpenMore, onLeave, moreOpen, leaveOpen, moreRef, leaveRef }) {
|
|
297
304
|
const live = useConnection().status === "live";
|
|
305
|
+
const { local } = useMedia();
|
|
298
306
|
const size = arrangement === "pad" ? 44 : 52;
|
|
299
307
|
const dockStyle = [styles.dock, arrangement === "pad" ? styles.pad : arrangement === "landscape" ? styles.landscape : styles.portrait];
|
|
300
308
|
const dockRef = useMeasuredRef("frame.dock", dockStyle);
|
|
301
309
|
const output = useAudioOutput();
|
|
302
310
|
return /* @__PURE__ */ jsxs(View, { accessibilityLabel: "Call controls", accessibilityRole: "toolbar", pointerEvents: "box-none", ref: dockRef, style: dockStyle, testID: "frame.dock", children: [
|
|
303
|
-
/* @__PURE__ */ jsx4(
|
|
304
|
-
|
|
311
|
+
/* @__PURE__ */ jsx4(
|
|
312
|
+
IconButton,
|
|
313
|
+
{
|
|
314
|
+
accessibilityLabel: microphoneOn ? "Mute microphone" : "Unmute microphone",
|
|
315
|
+
busy: local.microphone.state === "requesting",
|
|
316
|
+
icon: microphoneOn ? "mic" : "micOff",
|
|
317
|
+
off: !microphoneOn,
|
|
318
|
+
disabled: !live && !microphoneOn,
|
|
319
|
+
onCanvas: true,
|
|
320
|
+
onPress: onToggleMicrophone,
|
|
321
|
+
size,
|
|
322
|
+
testID: "dock.microphone"
|
|
323
|
+
}
|
|
324
|
+
),
|
|
325
|
+
/* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: cameraOn ? "Turn off camera" : "Turn on camera", busy: local.camera.state === "requesting", icon: cameraOn ? "cam" : "camOff", off: !cameraOn, disabled: !live && !cameraOn, onCanvas: true, onPress: onToggleCamera, size, testID: "dock.camera" }),
|
|
305
326
|
output ? /* @__PURE__ */ jsx4(AudioOutputButton, { captioned: arrangement === "portrait", output, size }) : null,
|
|
306
327
|
/* @__PURE__ */ jsx4(IconButton, { accessibilityLabel: "More options", expanded: moreOpen, icon: "more", onCanvas: true, onPress: onOpenMore, ref: moreRef, size, testID: "dock.more" }),
|
|
307
328
|
arrangement === "pad" ? /* @__PURE__ */ jsx4(View, { style: styles.gap }) : null,
|
|
@@ -403,12 +424,14 @@ var REACTIONS = [
|
|
|
403
424
|
function MoreSheet({ open, onClose, onOpenPeople, onOpenChat, inviteLink, returnFocusRef }) {
|
|
404
425
|
const client = useSpaceClient();
|
|
405
426
|
const self = useSelf();
|
|
427
|
+
const stage = useStageView();
|
|
406
428
|
const people2 = useParticipants().roster.length;
|
|
407
429
|
const toasts = useToasts();
|
|
408
430
|
const { soundsEnabled } = usePreferences();
|
|
409
431
|
const canRaiseHand = useCan("raiseHand");
|
|
410
432
|
const live = useConnection().status === "live";
|
|
411
433
|
const canReact = useCan("sendReaction") && live;
|
|
434
|
+
const canManageBoard = useCan("manageWhiteboard");
|
|
412
435
|
const fail = useCallback5((message2) => () => toasts.show({ kind: "error", dismissible: true, message: message2 }), [toasts]);
|
|
413
436
|
const toggleHand = useCallback5(() => {
|
|
414
437
|
onClose();
|
|
@@ -436,6 +459,27 @@ function MoreSheet({ open, onClose, onOpenPeople, onOpenChat, inviteLink, return
|
|
|
436
459
|
/* @__PURE__ */ jsxs3(SheetGroup, { children: [
|
|
437
460
|
inviteLink ? /* @__PURE__ */ jsx7(CopyLinkRow, { link: inviteLink }) : null,
|
|
438
461
|
inviteLink ? /* @__PURE__ */ jsx7(SheetRow, { icon: "iosShare", label: "Share link", onPress: () => shareLink(inviteLink), testID: "more.share" }) : null,
|
|
462
|
+
/* @__PURE__ */ jsx7(
|
|
463
|
+
SheetRow,
|
|
464
|
+
{
|
|
465
|
+
icon: "pen",
|
|
466
|
+
label: "Board",
|
|
467
|
+
onPress: () => {
|
|
468
|
+
onClose();
|
|
469
|
+
const transport = client.whiteboard.transport();
|
|
470
|
+
if (!transport) {
|
|
471
|
+
fail("The board is unavailable in this call.")();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
void transport.startSceneSubscription().then(async () => {
|
|
475
|
+
if (canManageBoard) await transport.setPresentation?.(true);
|
|
476
|
+
stage.setBoardOpen(true);
|
|
477
|
+
stage.showContent();
|
|
478
|
+
}).catch(fail("Couldn\u2019t open the board. Try again."));
|
|
479
|
+
},
|
|
480
|
+
testID: "more.board"
|
|
481
|
+
}
|
|
482
|
+
),
|
|
439
483
|
/* @__PURE__ */ jsx7(RecordingRow, { onDone: onClose }),
|
|
440
484
|
/* @__PURE__ */ jsx7(ChatRow, { onPress: onOpenChat }),
|
|
441
485
|
/* @__PURE__ */ jsx7(SheetRow, { end: /* @__PURE__ */ jsx7(PeopleCount, { count: people2 }), icon: "users", label: "People", onPress: onOpenPeople, testID: "more.people" }),
|
|
@@ -1606,10 +1650,33 @@ var styles11 = StyleSheet11.create({
|
|
|
1606
1650
|
});
|
|
1607
1651
|
|
|
1608
1652
|
// src/stage/Stage.tsx
|
|
1609
|
-
import { memo as memo11, useCallback as
|
|
1653
|
+
import { memo as memo11, useCallback as useCallback14, useEffect as useEffect16, useMemo as useMemo11, useState as useState13 } from "react";
|
|
1610
1654
|
import { Pressable as Pressable13, StyleSheet as StyleSheet18, View as View18 } from "react-native";
|
|
1611
1655
|
import Animated9 from "react-native-reanimated";
|
|
1612
1656
|
|
|
1657
|
+
// src/whiteboard/native-board-session.ts
|
|
1658
|
+
function ownNativeBoardSession(client, onError) {
|
|
1659
|
+
const transport = client.whiteboard.transport();
|
|
1660
|
+
if (!transport) return () => {
|
|
1661
|
+
};
|
|
1662
|
+
let started = false;
|
|
1663
|
+
let active = true;
|
|
1664
|
+
const observe = () => {
|
|
1665
|
+
if (started || client.getSnapshot().connection.status !== "live") return;
|
|
1666
|
+
started = true;
|
|
1667
|
+
void transport.startSceneSubscription().catch(() => {
|
|
1668
|
+
if (active) onError();
|
|
1669
|
+
});
|
|
1670
|
+
};
|
|
1671
|
+
const unsubscribe = client.subscribe(observe);
|
|
1672
|
+
observe();
|
|
1673
|
+
return () => {
|
|
1674
|
+
active = false;
|
|
1675
|
+
unsubscribe();
|
|
1676
|
+
if (started) void transport.stopSceneSubscription();
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1613
1680
|
// src/motion/MovingFrame.tsx
|
|
1614
1681
|
import { useEffect as useEffect11, useRef as useRef7 } from "react";
|
|
1615
1682
|
import { StyleSheet as StyleSheet12 } from "react-native";
|
|
@@ -1688,13 +1755,37 @@ var tileLeaving = () => {
|
|
|
1688
1755
|
};
|
|
1689
1756
|
|
|
1690
1757
|
// src/stage/ContentTile.tsx
|
|
1691
|
-
import {
|
|
1758
|
+
import { ChalkWhiteboardViewBounds } from "@q9labsai/chalk-client";
|
|
1759
|
+
import { memo as memo8, useCallback as useCallback11, useContext as useContext4, useEffect as useEffect13, useMemo as useMemo8, useRef as useRef10, useState as useState12 } from "react";
|
|
1692
1760
|
import { Pressable as Pressable11, StyleSheet as StyleSheet14, View as View14 } from "react-native";
|
|
1693
1761
|
|
|
1694
1762
|
// src/components/EmbeddedWhiteboard.tsx
|
|
1695
1763
|
import { ChalkWhiteboardController } from "@q9labsai/chalk-whiteboard/embedded";
|
|
1696
1764
|
import { useCallback as useCallback9, useEffect as useEffect12, useMemo as useMemo7, useRef as useRef8, useState as useState11 } from "react";
|
|
1697
1765
|
import { ActivityIndicator as ActivityIndicator2, Pressable as Pressable10, Text as Text2, useWindowDimensions, View as View12 } from "react-native";
|
|
1766
|
+
|
|
1767
|
+
// src/whiteboard/export-board-image.ts
|
|
1768
|
+
import { setImageAsync } from "expo-clipboard";
|
|
1769
|
+
import { File as File2, Paths } from "expo-file-system";
|
|
1770
|
+
import { isAvailableAsync, shareAsync } from "expo-sharing";
|
|
1771
|
+
async function exportBoardImage(value) {
|
|
1772
|
+
if (value.format !== "png" || !value.dataURL.startsWith("data:image/png;base64,")) throw new Error("Board export is not a PNG image");
|
|
1773
|
+
const base64 = value.dataURL.slice("data:image/png;base64,".length);
|
|
1774
|
+
if (value.action === "copy") {
|
|
1775
|
+
await setImageAsync(base64);
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
if (!await isAvailableAsync()) throw new Error("Image sharing is unavailable on this device");
|
|
1779
|
+
const file = new File2(Paths.cache, `chalk-board-${Date.now()}.png`);
|
|
1780
|
+
try {
|
|
1781
|
+
file.write(base64, { encoding: "base64" });
|
|
1782
|
+
await shareAsync(file.uri, { mimeType: "image/png", UTI: "public.png", dialogTitle: "Save or share the board", anchor: { x: 16, y: 16, width: 1, height: 1 } });
|
|
1783
|
+
} finally {
|
|
1784
|
+
if (file.exists) file.delete();
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
// src/components/EmbeddedWhiteboard.tsx
|
|
1698
1789
|
import WebView from "react-native-webview";
|
|
1699
1790
|
|
|
1700
1791
|
// src/whiteboard/embedded-whiteboard-assets.ts
|
|
@@ -1743,7 +1834,7 @@ var embeddedWhiteboardWebViewSecurityPolicy = Object.freeze({
|
|
|
1743
1834
|
allowFileAccessFromFileURLs: false,
|
|
1744
1835
|
allowUniversalAccessFromFileURLs: false,
|
|
1745
1836
|
cacheEnabled: false,
|
|
1746
|
-
domStorageEnabled:
|
|
1837
|
+
domStorageEnabled: true,
|
|
1747
1838
|
javaScriptCanOpenWindowsAutomatically: false,
|
|
1748
1839
|
javaScriptEnabled: true,
|
|
1749
1840
|
mixedContentMode: "never",
|
|
@@ -1751,11 +1842,41 @@ var embeddedWhiteboardWebViewSecurityPolicy = Object.freeze({
|
|
|
1751
1842
|
sharedCookiesEnabled: false,
|
|
1752
1843
|
thirdPartyCookiesEnabled: false
|
|
1753
1844
|
});
|
|
1754
|
-
function EmbeddedWhiteboard({
|
|
1845
|
+
function EmbeddedWhiteboard({
|
|
1846
|
+
board,
|
|
1847
|
+
onFollow,
|
|
1848
|
+
onCloseBoard,
|
|
1849
|
+
transport,
|
|
1850
|
+
journeyId,
|
|
1851
|
+
traceparent,
|
|
1852
|
+
tracestate,
|
|
1853
|
+
canDraw,
|
|
1854
|
+
canClear,
|
|
1855
|
+
theme: themeOverride,
|
|
1856
|
+
localParticipantColor,
|
|
1857
|
+
rendererURL: rendererURLOverride,
|
|
1858
|
+
style,
|
|
1859
|
+
testID,
|
|
1860
|
+
onMetric,
|
|
1861
|
+
onError,
|
|
1862
|
+
onUserExport
|
|
1863
|
+
}) {
|
|
1864
|
+
const toasts = useToasts();
|
|
1865
|
+
const noticesRef = useRef8(/* @__PURE__ */ new Map());
|
|
1866
|
+
const clearNotices = useCallback9(() => {
|
|
1867
|
+
noticesRef.current.forEach((id) => toasts.dismiss(id));
|
|
1868
|
+
noticesRef.current.clear();
|
|
1869
|
+
}, [toasts]);
|
|
1755
1870
|
const theme = themeOverride ?? "light";
|
|
1756
1871
|
const webViewRef = useRef8(null);
|
|
1757
1872
|
const controllerRef = useRef8(null);
|
|
1758
1873
|
const listenersRef = useRef8(/* @__PURE__ */ new Set());
|
|
1874
|
+
const boardRef = useRef8(board);
|
|
1875
|
+
boardRef.current = board;
|
|
1876
|
+
const onFollowRef = useRef8(onFollow);
|
|
1877
|
+
onFollowRef.current = onFollow;
|
|
1878
|
+
const onCloseBoardRef = useRef8(onCloseBoard);
|
|
1879
|
+
onCloseBoardRef.current = onCloseBoard;
|
|
1759
1880
|
const onMetricRef = useRef8(onMetric);
|
|
1760
1881
|
const onErrorRef = useRef8(onError);
|
|
1761
1882
|
const onUserExportRef = useRef8(onUserExport);
|
|
@@ -1784,7 +1905,13 @@ function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, can
|
|
|
1784
1905
|
);
|
|
1785
1906
|
const handleControllerError = useCallback9((error2) => onErrorRef.current?.(error2), []);
|
|
1786
1907
|
const handleControllerMetric = useCallback9((metric) => onMetricRef.current?.(metric), []);
|
|
1787
|
-
const handleControllerUserExport = useCallback9((value) =>
|
|
1908
|
+
const handleControllerUserExport = useCallback9(async (value) => {
|
|
1909
|
+
if (onUserExportRef.current) {
|
|
1910
|
+
await onUserExportRef.current(value);
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
await exportBoardImage(value);
|
|
1914
|
+
}, []);
|
|
1788
1915
|
useEffect12(() => {
|
|
1789
1916
|
let active = true;
|
|
1790
1917
|
setLoadError(null);
|
|
@@ -1808,6 +1935,41 @@ function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, can
|
|
|
1808
1935
|
journeyId,
|
|
1809
1936
|
...traceparent ? { traceparent } : {},
|
|
1810
1937
|
...tracestate ? { tracestate } : {},
|
|
1938
|
+
board: boardRef.current,
|
|
1939
|
+
manageSceneSubscription: false,
|
|
1940
|
+
onNotice: (notice) => {
|
|
1941
|
+
if (!notice) {
|
|
1942
|
+
clearNotices();
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
const toastId = toasts.show({
|
|
1946
|
+
kind: notice.kind,
|
|
1947
|
+
message: notice.message,
|
|
1948
|
+
dismissible: notice.kind === "error",
|
|
1949
|
+
...notice.actionLabel ? {
|
|
1950
|
+
actions: [
|
|
1951
|
+
{
|
|
1952
|
+
label: notice.actionLabel,
|
|
1953
|
+
onPress: () => {
|
|
1954
|
+
controller.performNoticeAction(notice.id);
|
|
1955
|
+
const id = noticesRef.current.get(notice.id);
|
|
1956
|
+
if (id !== void 0) toasts.dismiss(id);
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
]
|
|
1960
|
+
} : {}
|
|
1961
|
+
});
|
|
1962
|
+
noticesRef.current.set(notice.id, toastId);
|
|
1963
|
+
if (noticesRef.current.size > 8) {
|
|
1964
|
+
const oldest = noticesRef.current.entries().next().value;
|
|
1965
|
+
if (oldest) {
|
|
1966
|
+
toasts.dismiss(oldest[1]);
|
|
1967
|
+
noticesRef.current.delete(oldest[0]);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
},
|
|
1971
|
+
onFollow: (id) => onFollowRef.current?.(id),
|
|
1972
|
+
onCloseBoard: () => onCloseBoardRef.current?.(),
|
|
1811
1973
|
canDraw,
|
|
1812
1974
|
canClear,
|
|
1813
1975
|
theme,
|
|
@@ -1823,8 +1985,12 @@ function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, can
|
|
|
1823
1985
|
return () => {
|
|
1824
1986
|
if (controllerRef.current === controller) controllerRef.current = null;
|
|
1825
1987
|
controller.stop();
|
|
1988
|
+
clearNotices();
|
|
1826
1989
|
};
|
|
1827
|
-
}, [handleControllerError, handleControllerMetric, handleControllerUserExport, journeyId, localParticipantColor, rendererPort, theme, traceparent, tracestate, transport]);
|
|
1990
|
+
}, [clearNotices, toasts, handleControllerError, handleControllerMetric, handleControllerUserExport, journeyId, localParticipantColor, rendererPort, theme, traceparent, tracestate, transport]);
|
|
1991
|
+
useEffect12(() => {
|
|
1992
|
+
controllerRef.current?.setBoard(board);
|
|
1993
|
+
}, [board]);
|
|
1828
1994
|
useEffect12(() => {
|
|
1829
1995
|
controllerRef.current?.setCapabilities({ canDraw, canClear });
|
|
1830
1996
|
}, [canClear, canDraw]);
|
|
@@ -1842,6 +2008,7 @@ function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, can
|
|
|
1842
2008
|
};
|
|
1843
2009
|
const allowNavigation = (request) => Boolean(rendererURL && isEmbeddedWhiteboardNavigationAllowed(request.url, rendererURL));
|
|
1844
2010
|
const reloadRenderer = () => {
|
|
2011
|
+
clearNotices();
|
|
1845
2012
|
controllerRef.current?.rendererReloaded();
|
|
1846
2013
|
setRendererGeneration(createRendererGeneration());
|
|
1847
2014
|
};
|
|
@@ -1928,16 +2095,21 @@ function RtcVideoView(props) {
|
|
|
1928
2095
|
return /* @__PURE__ */ jsx21(RtcView, { ...props });
|
|
1929
2096
|
}
|
|
1930
2097
|
|
|
2098
|
+
// src/frame/call-controls.ts
|
|
2099
|
+
import { createContext as createContext4 } from "react";
|
|
2100
|
+
var LandscapeControlsContext = createContext4(false);
|
|
2101
|
+
|
|
1931
2102
|
// src/primitives/NameTag.tsx
|
|
1932
2103
|
import { memo as memo7 } from "react";
|
|
1933
2104
|
import { StyleSheet as StyleSheet13, View as View13 } from "react-native";
|
|
1934
2105
|
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1935
|
-
var NameTag = memo7(function NameTag2({ name, muted = false, pinned = false, icon, you = false, handRaised = false, handOrder, testID }) {
|
|
2106
|
+
var NameTag = memo7(function NameTag2({ name, muted = false, pinned = false, following = false, icon, you = false, handRaised = false, handOrder, testID }) {
|
|
1936
2107
|
const tagRef = useMeasuredRef(testID, styles13.tag);
|
|
1937
2108
|
return /* @__PURE__ */ jsx22(View13, { pointerEvents: "none", style: styles13.slot, children: /* @__PURE__ */ jsxs14(View13, { ref: tagRef, style: styles13.tag, testID, children: [
|
|
1938
2109
|
pinned ? /* @__PURE__ */ jsx22(Icon, { color: fixed.overlayText, name: "pin", size: 14 }) : null,
|
|
1939
2110
|
icon ? /* @__PURE__ */ jsx22(Icon, { color: fixed.overlayText, name: icon, size: 14 }) : null,
|
|
1940
2111
|
/* @__PURE__ */ jsx22(ChalkText, { color: fixed.overlayText, numberOfLines: 1, style: styles13.name, variant: "label", children: name }),
|
|
2112
|
+
following ? /* @__PURE__ */ jsx22(ChalkText, { color: fixed.overlayText, variant: "label", children: "following" }) : null,
|
|
1941
2113
|
you ? /* @__PURE__ */ jsx22(ChalkText, { color: fixed.overlayText, style: styles13.you, variant: "label", children: "(You)" }) : null,
|
|
1942
2114
|
muted ? /* @__PURE__ */ jsx22(Icon, { color: fixed.overlayDanger, name: "micOff", size: 14 }) : null,
|
|
1943
2115
|
handRaised ? /* @__PURE__ */ jsxs14(View13, { style: styles13.hand, children: [
|
|
@@ -2006,30 +2178,72 @@ function ScreenShare({ sharerId, inner, mini, onShowInSpotlight }) {
|
|
|
2006
2178
|
] });
|
|
2007
2179
|
}
|
|
2008
2180
|
var selectBoard = (snapshot) => snapshot.whiteboard.engine.status;
|
|
2181
|
+
var selectRoster = (snapshot) => snapshot.participants.roster;
|
|
2182
|
+
var selectSelfId = (snapshot) => snapshot.self.participantId;
|
|
2183
|
+
var selectConnection = (snapshot) => snapshot.connection.status;
|
|
2184
|
+
var selectAccess = (snapshot) => snapshot.whiteboard.access;
|
|
2185
|
+
var selectCanManage = (snapshot) => snapshot.self.can("manageWhiteboard");
|
|
2186
|
+
var selectSceneId = (snapshot) => snapshot.whiteboard.engine.sceneId;
|
|
2009
2187
|
function Board({ mini, onShowInSpotlight }) {
|
|
2010
2188
|
const client = useSpaceClient();
|
|
2011
2189
|
const { colors, scheme } = useTheme();
|
|
2190
|
+
const view = useStageView();
|
|
2191
|
+
const { width, height } = useDeviceLayout();
|
|
2192
|
+
const landscapeControlsVisible = useContext4(LandscapeControlsContext);
|
|
2193
|
+
const phone = Math.min(width, height) < 600;
|
|
2012
2194
|
const status = useSpaceSelector(selectBoard);
|
|
2013
|
-
const
|
|
2014
|
-
const
|
|
2195
|
+
const roster = useSpaceSelector(selectRoster);
|
|
2196
|
+
const selfId = useSpaceSelector(selectSelfId);
|
|
2197
|
+
const connectionStatus = useSpaceSelector(selectConnection);
|
|
2198
|
+
const sceneId = useSpaceSelector(selectSceneId);
|
|
2199
|
+
const access = useSpaceSelector(selectAccess);
|
|
2200
|
+
const canManage = useSpaceSelector(selectCanManage);
|
|
2201
|
+
const toasts = useToasts();
|
|
2015
2202
|
const transport = useMemo8(() => client.whiteboard.transport(), [client, status]);
|
|
2203
|
+
const [capabilities, setCapabilities] = useState12({ canDraw: false, canClear: false, viewsAvailable: false });
|
|
2204
|
+
useEffect13(() => transport?.subscribeSummary?.((summary) => setCapabilities({ canDraw: summary.canDraw, canClear: summary.canClear, viewsAvailable: transport.supportsViews === true })), [transport]);
|
|
2205
|
+
const board = useMemo8(
|
|
2206
|
+
() => ({
|
|
2207
|
+
primary: !mini,
|
|
2208
|
+
phone,
|
|
2209
|
+
landscapeControlsVisible,
|
|
2210
|
+
following: view.following,
|
|
2211
|
+
ownParticipantId: selfId,
|
|
2212
|
+
people: roster.map((person) => ({ id: person.participantId, displayName: person.displayName })),
|
|
2213
|
+
viewBounds: ChalkWhiteboardViewBounds,
|
|
2214
|
+
sceneId,
|
|
2215
|
+
sceneStatus: status,
|
|
2216
|
+
connectionStatus,
|
|
2217
|
+
viewsAvailable: capabilities.viewsAvailable,
|
|
2218
|
+
...canManage && access.policy !== null && transport?.setDrawPolicy ? {
|
|
2219
|
+
whoCanDraw: {
|
|
2220
|
+
policy: access.policy,
|
|
2221
|
+
people: roster.filter((person) => person.participantId !== selfId && !person.capabilities.includes("manageWhiteboard")).map((person) => ({ id: person.participantId, name: person.displayName, picked: access.permissions.some((permission) => permission.participantId === person.participantId && permission.canDraw) }))
|
|
2222
|
+
}
|
|
2223
|
+
} : {},
|
|
2224
|
+
colors
|
|
2225
|
+
}),
|
|
2226
|
+
[mini, phone, landscapeControlsVisible, view.following, selfId, roster, sceneId, status, connectionStatus, capabilities.viewsAvailable, canManage, access, transport, colors]
|
|
2227
|
+
);
|
|
2228
|
+
const onClose = useCallback11(() => {
|
|
2229
|
+
void (async () => {
|
|
2230
|
+
if (canManage) await transport?.setPresentation?.(false);
|
|
2231
|
+
view.setBoardOpen(false);
|
|
2232
|
+
view.setFollowing(null);
|
|
2233
|
+
})().catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t close the board. Try again." }));
|
|
2234
|
+
}, [canManage, transport, toasts, view.setBoardOpen, view.setFollowing]);
|
|
2016
2235
|
const journeyId = useRef10(`board-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`).current;
|
|
2017
2236
|
return /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
2018
|
-
transport ? /* @__PURE__ */ jsx23(EmbeddedWhiteboard, { canClear:
|
|
2237
|
+
transport ? /* @__PURE__ */ jsx23(EmbeddedWhiteboard, { board, canClear: capabilities.canClear, canDraw: !mini && capabilities.canDraw, journeyId, onCloseBoard: onClose, onFollow: view.setFollowing, style: StyleSheet14.absoluteFill, testID: "tile.content.board", theme: scheme, transport }) : null,
|
|
2019
2238
|
mini ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
2020
2239
|
/* @__PURE__ */ jsx23(Pressable11, { accessibilityLabel: "Show the board in spotlight", accessibilityRole: "button", onPress: onShowInSpotlight, style: StyleSheet14.absoluteFill, testID: "tile.content.open" }),
|
|
2021
2240
|
/* @__PURE__ */ jsx23(NameTag, { icon: "pen", name: "Board", testID: "tile.content.name" })
|
|
2022
|
-
] }) :
|
|
2023
|
-
/* @__PURE__ */ jsx23(Icon, { color: colors.textMuted, name: "lock", size: 16 }),
|
|
2024
|
-
/* @__PURE__ */ jsx23(ChalkText, { tone: "textSoft", variant: "section", children: "View only" })
|
|
2025
|
-
] })
|
|
2241
|
+
] }) : null
|
|
2026
2242
|
] });
|
|
2027
2243
|
}
|
|
2028
2244
|
var styles14 = StyleSheet14.create({
|
|
2029
2245
|
tile: { flex: 1, overflow: "hidden", borderRadius: radii.tilePhone },
|
|
2030
|
-
box: { position: "absolute", overflow: "hidden" }
|
|
2031
|
-
// `.vchip`: a 30 pt pill 12 pt in from the board's top-left corner, with a one-pixel ring.
|
|
2032
|
-
viewOnly: { position: "absolute", left: 12, top: 12, height: 30, paddingHorizontal: 12, borderRadius: radii.round, borderWidth: 1, flexDirection: "row", alignItems: "center", gap: 6, zIndex: 3 }
|
|
2246
|
+
box: { position: "absolute", overflow: "hidden" }
|
|
2033
2247
|
});
|
|
2034
2248
|
|
|
2035
2249
|
// src/stage/layout.ts
|
|
@@ -2198,7 +2412,7 @@ function nextStageOrder(previous, present, selfId, speaker) {
|
|
|
2198
2412
|
}
|
|
2199
2413
|
|
|
2200
2414
|
// src/stage/ParticipantTile.tsx
|
|
2201
|
-
import { memo as memo10, useCallback as
|
|
2415
|
+
import { memo as memo10, useCallback as useCallback12, useEffect as useEffect15, useMemo as useMemo9 } from "react";
|
|
2202
2416
|
import { Pressable as Pressable12, StyleSheet as StyleSheet16, View as View16 } from "react-native";
|
|
2203
2417
|
import { useSharedValue as useSharedValue3, withTiming as withTiming5 } from "react-native-reanimated";
|
|
2204
2418
|
|
|
@@ -2208,17 +2422,17 @@ function tileAvatarSize(width, height) {
|
|
|
2208
2422
|
}
|
|
2209
2423
|
|
|
2210
2424
|
// src/primitives/TileShell.tsx
|
|
2211
|
-
import { memo as memo9, useEffect as
|
|
2425
|
+
import { memo as memo9, useEffect as useEffect14 } from "react";
|
|
2212
2426
|
import { StyleSheet as StyleSheet15, View as View15 } from "react-native";
|
|
2213
2427
|
import Animated8, { useAnimatedStyle as useAnimatedStyle4, useSharedValue as useSharedValue2, withTiming as withTiming4 } from "react-native-reanimated";
|
|
2214
2428
|
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2215
|
-
var TileShell = memo9(function TileShell2({ children, speaking = false, cameraOn = false, level, testID }) {
|
|
2429
|
+
var TileShell = memo9(function TileShell2({ children, selected = false, speaking = false, cameraOn = false, level, testID }) {
|
|
2216
2430
|
const { colors } = useTheme();
|
|
2217
2431
|
const { phone } = useDeviceLayout();
|
|
2218
2432
|
const radius = phone ? radii.tilePhone : radii.tile;
|
|
2219
2433
|
const live = useSharedValue2(0);
|
|
2220
2434
|
const showRing = speaking && cameraOn;
|
|
2221
|
-
|
|
2435
|
+
useEffect14(() => {
|
|
2222
2436
|
live.value = withTiming4(showRing ? 1 : 0, timings.scrim);
|
|
2223
2437
|
}, [live, showRing]);
|
|
2224
2438
|
const ringStyle = useAnimatedStyle4(() => {
|
|
@@ -2227,6 +2441,7 @@ var TileShell = memo9(function TileShell2({ children, speaking = false, cameraOn
|
|
|
2227
2441
|
});
|
|
2228
2442
|
return /* @__PURE__ */ jsxs16(View15, { style: [styles15.tile, { borderRadius: radius, backgroundColor: colors.tile }], testID, children: [
|
|
2229
2443
|
children,
|
|
2444
|
+
selected ? /* @__PURE__ */ jsx24(View15, { pointerEvents: "none", style: [StyleSheet15.absoluteFill, { borderRadius: radius, borderWidth: 2, borderColor: colors.text, zIndex: 6 }] }) : null,
|
|
2230
2445
|
/* @__PURE__ */ jsx24(Animated8.View, { pointerEvents: "none", style: [styles15.ring, { borderRadius: radius }, ringStyle], testID: testID ? `${testID}.ring` : void 0, children: /* @__PURE__ */ jsx24(View15, { style: [styles15.ringShade, { borderRadius: radius - 3 }] }) })
|
|
2231
2446
|
] });
|
|
2232
2447
|
});
|
|
@@ -2270,12 +2485,12 @@ function selectTile(id) {
|
|
|
2270
2485
|
};
|
|
2271
2486
|
};
|
|
2272
2487
|
}
|
|
2273
|
-
var ParticipantTile = memo10(function ParticipantTile2({ id, width, height, float, pinned, mirror, onOpen }) {
|
|
2488
|
+
var ParticipantTile = memo10(function ParticipantTile2({ id, width, height, float, pinned, following = false, mirror, onOpen, onOptions }) {
|
|
2274
2489
|
const select = useMemo9(() => selectTile(id), [id]);
|
|
2275
2490
|
const tile = useSpaceSelector(select, shallowEqual);
|
|
2276
2491
|
const slot = useDevScenario().videoSlots?.[id];
|
|
2277
2492
|
const level = useSharedValue3(0);
|
|
2278
|
-
|
|
2493
|
+
useEffect15(() => {
|
|
2279
2494
|
level.value = withTiming5(tile.speaking ? 0.6 : 0, timings.level);
|
|
2280
2495
|
}, [level, tile.speaking]);
|
|
2281
2496
|
const streamURL = useMemo9(() => tile.track ? createNativeMediaStream(tile.track).toURL() : null, [tile.track]);
|
|
@@ -2286,10 +2501,10 @@ var ParticipantTile = memo10(function ParticipantTile2({ id, width, height, floa
|
|
|
2286
2501
|
const state = `${tile.muted ? ", microphone off" : ""}${tile.handRaised ? ", hand raised" : ""}`;
|
|
2287
2502
|
const hitRef = useMeasuredRef(`tile.${id}.open`, StyleSheet16.absoluteFill);
|
|
2288
2503
|
const label = `Options for ${tile.name}${tile.isSelf ? " (you)" : ""}${pinned ? ", pinned" : ""}${state}`;
|
|
2289
|
-
return /* @__PURE__ */ jsxs17(TileShell, { cameraOn: video !== null, level, speaking: tile.speaking, testID: `tile.${id}`, children: [
|
|
2504
|
+
return /* @__PURE__ */ jsxs17(TileShell, { selected: following, cameraOn: video !== null, level, speaking: tile.speaking, testID: `tile.${id}`, children: [
|
|
2290
2505
|
video ?? /* @__PURE__ */ jsx25(View16, { style: styles16.center, children: /* @__PURE__ */ jsx25(FaceAvatar, { level, lookAround: true, name: tile.name, size: tileAvatarSize(width, height - nameTagZone), style: "bold" }) }),
|
|
2291
|
-
/* @__PURE__ */ jsx25(Pressable12, { accessibilityHint: "Opens a sheet", accessibilityLabel: label, accessibilityRole: "button", onPress: () => onOpen(id), ref: hitRef, style: StyleSheet16.absoluteFill, testID: `tile.${id}.open` }),
|
|
2292
|
-
/* @__PURE__ */ jsx25(NameTag, { handRaised: tile.handRaised, muted: tile.muted, name, pinned, testID: `tile.${id}.name`, you }),
|
|
2506
|
+
/* @__PURE__ */ jsx25(Pressable12, { accessibilityHint: "Opens a sheet", accessibilityLabel: label, accessibilityRole: "button", onPress: () => onOpen(id), onLongPress: () => onOptions?.(id), ref: hitRef, style: StyleSheet16.absoluteFill, testID: `tile.${id}.open` }),
|
|
2507
|
+
/* @__PURE__ */ jsx25(NameTag, { following, handRaised: tile.handRaised, muted: tile.muted, name, pinned, testID: `tile.${id}.name`, you }),
|
|
2293
2508
|
tile.isSelf && video !== null ? /* @__PURE__ */ jsx25(FlipCameraButton, { back: tile.back, float, testID: `tile.${id}.flip` }) : null
|
|
2294
2509
|
] });
|
|
2295
2510
|
});
|
|
@@ -2303,7 +2518,7 @@ function FlipCameraButton({ back, float, testID }) {
|
|
|
2303
2518
|
const client = useSpaceClient();
|
|
2304
2519
|
const toasts = useToasts();
|
|
2305
2520
|
const other = useSpaceSelector(selectOtherCamera);
|
|
2306
|
-
const flip =
|
|
2521
|
+
const flip = useCallback12(() => {
|
|
2307
2522
|
if (other === null) return;
|
|
2308
2523
|
client.media.selectCamera(other).catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn't switch the camera." }));
|
|
2309
2524
|
}, [client, other, toasts]);
|
|
@@ -2321,10 +2536,10 @@ var styles16 = StyleSheet16.create({
|
|
|
2321
2536
|
});
|
|
2322
2537
|
|
|
2323
2538
|
// src/stage/TileSheet.tsx
|
|
2324
|
-
import { useCallback as
|
|
2539
|
+
import { useCallback as useCallback13, useMemo as useMemo10 } from "react";
|
|
2325
2540
|
import { StyleSheet as StyleSheet17, View as View17 } from "react-native";
|
|
2326
2541
|
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2327
|
-
var closed = { name: "", isSelf: false, cameraOn: false, back: false, otherCamera: null, muted: false, canMute: false, canRemove: false };
|
|
2542
|
+
var closed = { boardOpen: false, name: "", isSelf: false, cameraOn: false, back: false, otherCamera: null, muted: false, canMute: false, canRemove: false };
|
|
2328
2543
|
function TileSheet({ participantId, open, onClose }) {
|
|
2329
2544
|
const client = useSpaceClient();
|
|
2330
2545
|
const toasts = useToasts();
|
|
@@ -2335,6 +2550,7 @@ function TileSheet({ participantId, open, onClose }) {
|
|
|
2335
2550
|
const person2 = snapshot.participants.roster.find((participant) => participant.participantId === participantId);
|
|
2336
2551
|
const isSelf = snapshot.self.participantId === participantId;
|
|
2337
2552
|
return {
|
|
2553
|
+
boardOpen: snapshot.whiteboard.engine.presenting,
|
|
2338
2554
|
name: person2?.displayName ?? snapshot.self.displayName ?? "",
|
|
2339
2555
|
isSelf,
|
|
2340
2556
|
cameraOn: isSelf && snapshot.media.local.camera.state === "enabled",
|
|
@@ -2348,8 +2564,10 @@ function TileSheet({ participantId, open, onClose }) {
|
|
|
2348
2564
|
[participantId]
|
|
2349
2565
|
);
|
|
2350
2566
|
const person = useSpaceSelector(select, shallowEqual);
|
|
2567
|
+
const selectViewsAvailable = useCallback13(() => client.whiteboard.transport()?.supportsViews === true, [client]);
|
|
2568
|
+
const viewsAvailable = useSpaceSelector(selectViewsAvailable);
|
|
2351
2569
|
const id = participantId ?? "";
|
|
2352
|
-
const failed =
|
|
2570
|
+
const failed = useCallback13((message2) => () => toasts.show({ kind: "error", dismissible: true, message: message2 }), [toasts]);
|
|
2353
2571
|
const run = (action) => () => {
|
|
2354
2572
|
onClose();
|
|
2355
2573
|
action();
|
|
@@ -2360,6 +2578,18 @@ function TileSheet({ participantId, open, onClose }) {
|
|
|
2360
2578
|
/* @__PURE__ */ jsx26(ChalkText, { numberOfLines: 1, style: styles17.name, variant: "sheetTitle", children: `${person.name}${person.isSelf ? " (You)" : ""}` })
|
|
2361
2579
|
] }),
|
|
2362
2580
|
/* @__PURE__ */ jsxs18(SheetGroup, { children: [
|
|
2581
|
+
(view.boardOpen ?? person.boardOpen) && viewsAvailable && !person.isSelf ? /* @__PURE__ */ jsx26(
|
|
2582
|
+
SheetRow,
|
|
2583
|
+
{
|
|
2584
|
+
icon: "pin",
|
|
2585
|
+
label: view.following === participantId ? "Stop following" : "Follow",
|
|
2586
|
+
onPress: run(() => {
|
|
2587
|
+
view.showContent();
|
|
2588
|
+
view.setFollowing(view.following === participantId ? null : id);
|
|
2589
|
+
}),
|
|
2590
|
+
testID: "tile-sheet.follow"
|
|
2591
|
+
}
|
|
2592
|
+
) : null,
|
|
2363
2593
|
/* @__PURE__ */ jsx26(SheetRow, { icon: "pin", label: view.pinned === participantId ? "Unpin" : "Pin", onPress: run(() => view.togglePin(id)), testID: "tile-sheet.pin" }),
|
|
2364
2594
|
person.cameraOn && person.otherCamera !== null ? /* @__PURE__ */ jsx26(
|
|
2365
2595
|
SheetRow,
|
|
@@ -2411,20 +2641,33 @@ function selectStructure(snapshot) {
|
|
|
2411
2641
|
present: (hasSelf && selfId !== null ? [selfId, ...others] : others).join("\n"),
|
|
2412
2642
|
speaker: roster.find((person) => person.presence.activeSpeaker)?.participantId ?? null,
|
|
2413
2643
|
sharer: roster.find((person) => person.participantId !== selfId && person.media.screenShare === "active")?.participantId ?? null,
|
|
2414
|
-
board: snapshot.whiteboard.
|
|
2644
|
+
board: snapshot.whiteboard.engine.presenting
|
|
2415
2645
|
};
|
|
2416
2646
|
}
|
|
2417
2647
|
var Stage = memo11(function Stage2({ frame, onOpenPeople }) {
|
|
2648
|
+
const client = useSpaceClient();
|
|
2649
|
+
const toasts = useToasts();
|
|
2650
|
+
useEffect16(() => ownNativeBoardSession(client, () => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t open the board. Try again from More." })), [client, toasts]);
|
|
2418
2651
|
const structure = useSpaceSelector(selectStructure, shallowEqual);
|
|
2652
|
+
const selectViewsAvailable = useCallback14(() => client.whiteboard.transport()?.supportsViews === true, [client]);
|
|
2653
|
+
const viewsAvailable = useSpaceSelector(selectViewsAvailable);
|
|
2419
2654
|
const view = useStageView();
|
|
2420
2655
|
const { arrangement } = useDeviceLayout();
|
|
2421
2656
|
const { shareAspect } = useDevScenario();
|
|
2422
|
-
const [sheet, setSheet] =
|
|
2657
|
+
const [sheet, setSheet] = useState13({ id: null, open: false });
|
|
2658
|
+
useEffect16(() => {
|
|
2659
|
+
if (view.following && !structure.present.split("\n").includes(view.following)) view.setFollowing(null);
|
|
2660
|
+
}, [structure.present, view.following, view.setFollowing]);
|
|
2423
2661
|
const present = useMemo11(() => structure.present ? structure.present.split("\n") : [], [structure.present]);
|
|
2424
|
-
const [order, setOrder] =
|
|
2662
|
+
const [order, setOrder] = useState13({ order: [], spot: null });
|
|
2425
2663
|
const next = nextStageOrder(order, present, structure.selfId, structure.speaker);
|
|
2426
2664
|
if (next !== order) setOrder(next);
|
|
2427
|
-
|
|
2665
|
+
useEffect16(() => {
|
|
2666
|
+
view.setBoardOpen(null);
|
|
2667
|
+
view.setFollowing(null);
|
|
2668
|
+
}, [structure.board, view.setBoardOpen, view.setFollowing]);
|
|
2669
|
+
const boardVisible = view.boardOpen ?? structure.board;
|
|
2670
|
+
const content = useMemo11(() => boardVisible ? { kind: "board" } : structure.sharer !== null ? { kind: "screen", sharerId: structure.sharer } : null, [boardVisible, structure.sharer]);
|
|
2428
2671
|
const pinned = view.pinned !== null && present.includes(view.pinned) ? view.pinned : null;
|
|
2429
2672
|
const items = useMemo11(
|
|
2430
2673
|
() => stageLayout({
|
|
@@ -2439,21 +2682,32 @@ var Stage = memo11(function Stage2({ frame, onOpenPeople }) {
|
|
|
2439
2682
|
}),
|
|
2440
2683
|
[arrangement, content, frame, next, pinned, shareAspect, view.layout]
|
|
2441
2684
|
);
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2685
|
+
const followTile = useCallback14(
|
|
2686
|
+
(id) => {
|
|
2687
|
+
if (!boardVisible || !viewsAvailable || id === structure.selfId) {
|
|
2688
|
+
setSheet({ id, open: true });
|
|
2689
|
+
return;
|
|
2690
|
+
}
|
|
2691
|
+
view.showContent();
|
|
2692
|
+
view.setFollowing(view.following === id ? null : id);
|
|
2693
|
+
},
|
|
2694
|
+
[boardVisible, viewsAvailable, structure.selfId, view]
|
|
2695
|
+
);
|
|
2696
|
+
const openTile = useCallback14((id) => setSheet({ id, open: true }), []);
|
|
2697
|
+
const closeTile = useCallback14(() => setSheet((current) => ({ ...current, open: false })), []);
|
|
2444
2698
|
const stageRef = useMeasuredRef("frame.stage", styles18.layer);
|
|
2445
2699
|
return /* @__PURE__ */ jsxs19(View18, { pointerEvents: "box-none", ref: stageRef, style: styles18.layer, testID: "frame.stage", children: [
|
|
2446
|
-
items.map((item) => /* @__PURE__ */ jsx27(StageTile, { content, item, mirror: view.mirror, onOpenPeople, onOpenTile: openTile, onShowContent: view.showContent, peopleCount: present.length, pinned }, itemKey(item))),
|
|
2700
|
+
items.map((item) => /* @__PURE__ */ jsx27(StageTile, { content, item, mirror: view.mirror, onOpenPeople, onOpenTile: followTile, onTileOptions: openTile, following: view.following, onShowContent: view.showContent, peopleCount: present.length, pinned }, itemKey(item))),
|
|
2447
2701
|
/* @__PURE__ */ jsx27(TileSheet, { onClose: closeTile, open: sheet.open, participantId: sheet.id })
|
|
2448
2702
|
] });
|
|
2449
2703
|
});
|
|
2450
2704
|
function itemKey(item) {
|
|
2451
2705
|
return item.kind === "person" ? `person:${item.id}` : item.kind;
|
|
2452
2706
|
}
|
|
2453
|
-
function StageTile({ item, content, pinned, mirror, peopleCount, onOpenTile, onOpenPeople, onShowContent }) {
|
|
2707
|
+
function StageTile({ item, content, pinned, mirror, peopleCount, onOpenTile, onOpenPeople, onShowContent, following, onTileOptions }) {
|
|
2454
2708
|
const { scheme } = useTheme();
|
|
2455
2709
|
const float = item.kind === "person" && item.float;
|
|
2456
|
-
return /* @__PURE__ */ jsx27(MovingFrame, { frame: item.frame, style: float ? [styles18.float, { boxShadow: elevations[scheme].floatTile }] : null, children: /* @__PURE__ */ jsx27(Animated9.View, { entering: tileEntering, exiting: tileLeaving, style: styles18.fill, children: item.kind === "person" ? /* @__PURE__ */ jsx27(ParticipantTile, { float, height: item.frame.height, id: item.id, mirror, onOpen: onOpenTile, pinned: pinned === item.id, width: item.frame.width }) : item.kind === "content" && content ? /* @__PURE__ */ jsx27(ContentTile, { content, inner: item.inner, mini: item.mini, onShowInSpotlight: onShowContent }) : item.kind === "more" ? /* @__PURE__ */ jsx27(MoreTile, { count: item.count, onPress: onOpenPeople, peopleCount }) : null }) });
|
|
2710
|
+
return /* @__PURE__ */ jsx27(MovingFrame, { frame: item.frame, style: float ? [styles18.float, { boxShadow: elevations[scheme].floatTile }] : null, children: /* @__PURE__ */ jsx27(Animated9.View, { entering: tileEntering, exiting: tileLeaving, style: styles18.fill, children: item.kind === "person" ? /* @__PURE__ */ jsx27(ParticipantTile, { float, height: item.frame.height, id: item.id, mirror, onOpen: onOpenTile, onOptions: onTileOptions, following: following === item.id, pinned: pinned === item.id, width: item.frame.width }) : item.kind === "content" && content ? /* @__PURE__ */ jsx27(ContentTile, { content, inner: item.inner, mini: item.mini, onShowInSpotlight: onShowContent }) : item.kind === "more" ? /* @__PURE__ */ jsx27(MoreTile, { count: item.count, onPress: onOpenPeople, peopleCount }) : null }) });
|
|
2457
2711
|
}
|
|
2458
2712
|
var MoreTile = memo11(function MoreTile2({ count, peopleCount, onPress }) {
|
|
2459
2713
|
const { colors } = useTheme();
|
|
@@ -2469,12 +2723,33 @@ var styles18 = StyleSheet18.create({
|
|
|
2469
2723
|
moreText: { fontFamily: fontFamilies[600], fontSize: 22, lineHeight: 22 * 1.4 }
|
|
2470
2724
|
});
|
|
2471
2725
|
|
|
2726
|
+
// src/frame/use-landscape-chrome.ts
|
|
2727
|
+
import { useCallback as useCallback15, useEffect as useEffect17, useState as useState14 } from "react";
|
|
2728
|
+
function useLandscapeChrome({ fades, boardVisible }) {
|
|
2729
|
+
const canHide = fades && !boardVisible;
|
|
2730
|
+
const [hidden, setHidden] = useState14(false);
|
|
2731
|
+
const [shownAt, setShownAt] = useState14(0);
|
|
2732
|
+
useEffect17(() => {
|
|
2733
|
+
if (!canHide) {
|
|
2734
|
+
setHidden(false);
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
const timer = setTimeout(() => setHidden(true), durations.landscapeHide);
|
|
2738
|
+
return () => clearTimeout(timer);
|
|
2739
|
+
}, [canHide, shownAt]);
|
|
2740
|
+
const show = useCallback15(() => {
|
|
2741
|
+
setHidden(false);
|
|
2742
|
+
setShownAt(Date.now());
|
|
2743
|
+
}, []);
|
|
2744
|
+
return { hidden: canHide && hidden, show };
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2472
2747
|
// src/status/CallOverlays.tsx
|
|
2473
|
-
import { useEffect as
|
|
2748
|
+
import { useEffect as useEffect20 } from "react";
|
|
2474
2749
|
import { StyleSheet as StyleSheet21, View as View20 } from "react-native";
|
|
2475
2750
|
|
|
2476
2751
|
// src/limbo/Veil.tsx
|
|
2477
|
-
import { useEffect as
|
|
2752
|
+
import { useEffect as useEffect18 } from "react";
|
|
2478
2753
|
import { StyleSheet as StyleSheet19 } from "react-native";
|
|
2479
2754
|
import Animated10, { ReduceMotion as ReduceMotion2, useAnimatedStyle as useAnimatedStyle5, useSharedValue as useSharedValue4, withTiming as withTiming6 } from "react-native-reanimated";
|
|
2480
2755
|
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
@@ -2483,7 +2758,7 @@ var LIFT_FROM = 0.6;
|
|
|
2483
2758
|
function Veil({ level }) {
|
|
2484
2759
|
const { colors } = useTheme();
|
|
2485
2760
|
const opacity = useSharedValue4(OPACITY[level]);
|
|
2486
|
-
|
|
2761
|
+
useEffect18(() => {
|
|
2487
2762
|
if (level !== "none") {
|
|
2488
2763
|
opacity.value = OPACITY[level];
|
|
2489
2764
|
return;
|
|
@@ -2500,7 +2775,7 @@ function Veil({ level }) {
|
|
|
2500
2775
|
}
|
|
2501
2776
|
|
|
2502
2777
|
// src/status/StatusPage.tsx
|
|
2503
|
-
import { forwardRef as forwardRef3, memo as memo12, useEffect as
|
|
2778
|
+
import { forwardRef as forwardRef3, memo as memo12, useEffect as useEffect19, useRef as useRef11 } from "react";
|
|
2504
2779
|
import { AccessibilityInfo as AccessibilityInfo2, findNodeHandle as findNodeHandle2, Pressable as Pressable14, StyleSheet as StyleSheet20, View as View19 } from "react-native";
|
|
2505
2780
|
import Animated11, { useAnimatedStyle as useAnimatedStyle6 } from "react-native-reanimated";
|
|
2506
2781
|
import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
@@ -2526,7 +2801,7 @@ function StatusPage({ outcome, callName, onRejoin, onHome }) {
|
|
|
2526
2801
|
const pageStyle = [styles19.page, { backgroundColor: colors.canvas }];
|
|
2527
2802
|
const ref = useMeasuredRef("status.page", pageStyle);
|
|
2528
2803
|
const firstAction = useRef11(null);
|
|
2529
|
-
|
|
2804
|
+
useEffect19(() => {
|
|
2530
2805
|
const node = firstAction.current && findNodeHandle2(firstAction.current);
|
|
2531
2806
|
if (node) AccessibilityInfo2.setAccessibilityFocus(node);
|
|
2532
2807
|
}, [outcome]);
|
|
@@ -2579,7 +2854,7 @@ function CallOverlays({ screen, callName, rejoining, onHold, onRejoin, onHome })
|
|
|
2579
2854
|
useBackHandler(screen.kind === "status", onHome);
|
|
2580
2855
|
const { clear } = useToasts();
|
|
2581
2856
|
const clearsNotices = screen.kind === "status" || screen.kind === "joining";
|
|
2582
|
-
|
|
2857
|
+
useEffect20(() => {
|
|
2583
2858
|
if (clearsNotices) clear();
|
|
2584
2859
|
}, [clear, clearsNotices]);
|
|
2585
2860
|
const limbo = screen.kind === "joining" ? { kind: "joining", rejoining } : screen.kind === "call" && onHold ? { kind: "hold" } : null;
|
|
@@ -2630,7 +2905,7 @@ function callScreen(connection, leftByChoice) {
|
|
|
2630
2905
|
|
|
2631
2906
|
// src/toasts/CallEventToasts.tsx
|
|
2632
2907
|
import { SpaceClientError } from "@q9labsai/chalk-client";
|
|
2633
|
-
import { useCallback as
|
|
2908
|
+
import { useCallback as useCallback16, useEffect as useEffect21, useRef as useRef12 } from "react";
|
|
2634
2909
|
import { Linking as Linking2, Platform as Platform7 } from "react-native";
|
|
2635
2910
|
|
|
2636
2911
|
// src/toasts/media-failure-copy.ts
|
|
@@ -2688,7 +2963,7 @@ function useCallEventToasts({ onOpenSettings, resumedAfterSettings }) {
|
|
|
2688
2963
|
const ownMicrophoneChange = useRef12(false);
|
|
2689
2964
|
const latest = useRef12({ colors, soundsEnabled });
|
|
2690
2965
|
latest.current = { colors, soundsEnabled };
|
|
2691
|
-
|
|
2966
|
+
useEffect21(() => {
|
|
2692
2967
|
let previous = client.getSnapshot();
|
|
2693
2968
|
return client.subscribe(() => {
|
|
2694
2969
|
const next = client.getSnapshot();
|
|
@@ -2705,10 +2980,10 @@ function useCallEventToasts({ onOpenSettings, resumedAfterSettings }) {
|
|
|
2705
2980
|
});
|
|
2706
2981
|
}, [client, toasts]);
|
|
2707
2982
|
useResumedAfterSettings(resumedAfterSettings, toasts);
|
|
2708
|
-
const noteOwnMicrophoneChange =
|
|
2983
|
+
const noteOwnMicrophoneChange = useCallback16(() => {
|
|
2709
2984
|
ownMicrophoneChange.current = true;
|
|
2710
2985
|
}, []);
|
|
2711
|
-
const reportMediaFailure =
|
|
2986
|
+
const reportMediaFailure = useCallback16(
|
|
2712
2987
|
function reportMediaFailure2(permission, cause, retry) {
|
|
2713
2988
|
const code = cause instanceof SpaceClientError ? cause.code : null;
|
|
2714
2989
|
const icon = permission === "microphone" ? "micOff" : "camOff";
|
|
@@ -2773,7 +3048,7 @@ function useResumedAfterSettings(permission, toasts) {
|
|
|
2773
3048
|
const client = useSpaceClient();
|
|
2774
3049
|
const { colors } = useTheme();
|
|
2775
3050
|
const shown = useRef12(false);
|
|
2776
|
-
|
|
3051
|
+
useEffect21(() => {
|
|
2777
3052
|
if (!permission) return;
|
|
2778
3053
|
const check = () => {
|
|
2779
3054
|
if (shown.current || client.getSnapshot().connection.status !== "live") return;
|
|
@@ -2838,31 +3113,31 @@ function CallFrame({ displayName, callName = "Call", inviteLink, onLeave, onOpen
|
|
|
2838
3113
|
const { soundsEnabled } = usePreferences();
|
|
2839
3114
|
const toasts = useToasts();
|
|
2840
3115
|
const callEvents = useCallEventToasts({ onOpenSettings, resumedAfterSettings });
|
|
2841
|
-
const [leftByChoice, setLeftByChoice] =
|
|
2842
|
-
const [sheet, setSheet] =
|
|
3116
|
+
const [leftByChoice, setLeftByChoice] = useState15(false);
|
|
3117
|
+
const [sheet, setSheet] = useState15(null);
|
|
2843
3118
|
const moreRef = useRef13(null);
|
|
2844
3119
|
const leaveRef = useRef13(null);
|
|
2845
3120
|
const nameRef = useRef13(null);
|
|
2846
3121
|
const canEnd = useCan("endEpisode");
|
|
2847
|
-
const [leaveMenuOpen, setLeaveMenuOpen] =
|
|
3122
|
+
const [leaveMenuOpen, setLeaveMenuOpen] = useState15(false);
|
|
2848
3123
|
const sheetCount = usePortalCount("sheets");
|
|
2849
3124
|
const menuCount = usePortalCount("menus");
|
|
2850
3125
|
const layered = sheetCount > 0 || menuCount > 0;
|
|
2851
3126
|
const regions = useMemo12(() => frameRegions(layout.arrangement, layout.width, layout.height, layout.insets), [layout]);
|
|
2852
3127
|
const screenStyle = [styles21.root, { backgroundColor: colors.canvas }];
|
|
2853
3128
|
const screenRef = useMeasuredRef("frame.screen", screenStyle);
|
|
2854
|
-
const join2 =
|
|
3129
|
+
const join2 = useCallback17(() => {
|
|
2855
3130
|
setLeftByChoice(false);
|
|
2856
3131
|
client.join({ displayName, microphone: false, camera: false }).catch(() => void 0);
|
|
2857
3132
|
}, [client, displayName]);
|
|
2858
|
-
|
|
3133
|
+
useEffect22(() => {
|
|
2859
3134
|
if (client.getSnapshot().connection.status === "idle") join2();
|
|
2860
3135
|
}, [client, join2]);
|
|
2861
3136
|
useAndroidCallService();
|
|
2862
3137
|
const microphoneOn = media.local.microphone.state === "enabled";
|
|
2863
3138
|
const cameraOn = media.local.camera.state === "enabled";
|
|
2864
3139
|
const { noteOwnMicrophoneChange, reportMediaFailure } = callEvents;
|
|
2865
|
-
const toggleMicrophone =
|
|
3140
|
+
const toggleMicrophone = useCallback17(() => {
|
|
2866
3141
|
haptics.mute();
|
|
2867
3142
|
playSound(microphoneOn ? "mute" : "unmute", soundsEnabled);
|
|
2868
3143
|
if (microphoneOn) noteOwnMicrophoneChange();
|
|
@@ -2870,12 +3145,12 @@ function CallFrame({ displayName, callName = "Call", inviteLink, onLeave, onOpen
|
|
|
2870
3145
|
if (microphoneOn) client.media.setMicrophoneEnabled(false).catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t mute your microphone." }));
|
|
2871
3146
|
else void turnOn().catch((cause) => reportMediaFailure("microphone", cause, turnOn));
|
|
2872
3147
|
}, [client, microphoneOn, noteOwnMicrophoneChange, reportMediaFailure, soundsEnabled, toasts]);
|
|
2873
|
-
const toggleCamera =
|
|
3148
|
+
const toggleCamera = useCallback17(() => {
|
|
2874
3149
|
const turnOn = () => client.media.setCameraEnabled(true);
|
|
2875
3150
|
if (cameraOn) client.media.setCameraEnabled(false).catch(() => toasts.show({ kind: "error", dismissible: true, message: "Couldn\u2019t turn off your camera." }));
|
|
2876
3151
|
else void turnOn().catch((cause) => reportMediaFailure("camera", cause, turnOn));
|
|
2877
3152
|
}, [cameraOn, client, reportMediaFailure, toasts]);
|
|
2878
|
-
const exit =
|
|
3153
|
+
const exit = useCallback17(
|
|
2879
3154
|
(how) => {
|
|
2880
3155
|
setSheet(null);
|
|
2881
3156
|
setLeaveMenuOpen(false);
|
|
@@ -2886,26 +3161,36 @@ function CallFrame({ displayName, callName = "Call", inviteLink, onLeave, onOpen
|
|
|
2886
3161
|
},
|
|
2887
3162
|
[client, toasts]
|
|
2888
3163
|
);
|
|
2889
|
-
const pressLeave =
|
|
3164
|
+
const pressLeave = useCallback17(() => {
|
|
2890
3165
|
haptics.leave();
|
|
2891
3166
|
if (canEnd) setLeaveMenuOpen((open) => !open);
|
|
2892
3167
|
else exit("leave");
|
|
2893
3168
|
}, [canEnd, exit]);
|
|
2894
3169
|
const devScenario = useDevScenario();
|
|
2895
|
-
|
|
3170
|
+
useEffect22(() => {
|
|
2896
3171
|
if (devScenario.sheet && devScenario.sheet !== "route") setSheet(devScenario.sheet);
|
|
2897
3172
|
if (devScenario.menu === "leave") setLeaveMenuOpen(true);
|
|
2898
3173
|
}, [devScenario]);
|
|
2899
|
-
const
|
|
3174
|
+
const sharedBoard = useWhiteboard().engine.presenting;
|
|
3175
|
+
const boardVisible = useStageView().boardOpen ?? sharedBoard;
|
|
3176
|
+
const chrome = useLandscapeChrome({ fades: layout.arrangement === "landscape" && sheet === null && !layered, boardVisible });
|
|
3177
|
+
const chromeOpacity = useSharedValue5(1);
|
|
3178
|
+
useEffect22(() => {
|
|
3179
|
+
chromeOpacity.value = withTiming7(chrome.hidden ? 0 : 1, timings.fade);
|
|
3180
|
+
}, [chrome.hidden, chromeOpacity]);
|
|
3181
|
+
const chromeStyle = useAnimatedStyle7(() => {
|
|
3182
|
+
"worklet";
|
|
3183
|
+
return { opacity: chromeOpacity.value };
|
|
3184
|
+
});
|
|
2900
3185
|
const forced = devScenario.callState;
|
|
2901
3186
|
const screen = forced === "hold" ? { kind: "call" } : forced === "left" || forced === "ended" || forced === "failed" || forced === "removed" || forced === "exited" ? { kind: "status", outcome: forced } : callScreen(connection, leftByChoice);
|
|
2902
3187
|
return /* @__PURE__ */ jsxs22(View22, { ref: screenRef, style: screenStyle, testID: "frame.screen", children: [
|
|
2903
3188
|
/* @__PURE__ */ jsx33(StatusBar, { barStyle: scheme === "dark" ? "light-content" : "dark-content" }),
|
|
2904
3189
|
/* @__PURE__ */ jsxs22(View22, { accessibilityElementsHidden: layered, importantForAccessibility: layered ? "no-hide-descendants" : "auto", style: StyleSheet23.absoluteFill, children: [
|
|
2905
|
-
/* @__PURE__ */ jsx33(Stage, { frame: regions.stage, onOpenPeople: () => setSheet("people") }),
|
|
3190
|
+
/* @__PURE__ */ jsx33(LandscapeControlsContext.Provider, { value: layout.arrangement === "landscape" && !chrome.hidden, children: /* @__PURE__ */ jsx33(Stage, { frame: regions.stage, onOpenPeople: () => setSheet("people") }) }),
|
|
2906
3191
|
chrome.hidden ? /* @__PURE__ */ jsx33(Pressable15, { accessibilityLabel: "Show call controls", onPress: chrome.show, style: StyleSheet23.absoluteFill, testID: "frame.show-controls" }) : null,
|
|
2907
|
-
/* @__PURE__ */ jsx33(Animated12.View, { pointerEvents: chrome.hidden ? "none" : "box-none", style: [styles21.region, frameStyle(regions.header),
|
|
2908
|
-
/* @__PURE__ */ jsx33(Animated12.View, { pointerEvents: chrome.hidden ? "none" : "box-none", style: [styles21.region, frameStyle(regions.dock),
|
|
3192
|
+
/* @__PURE__ */ jsx33(Animated12.View, { pointerEvents: chrome.hidden ? "none" : "box-none", style: [styles21.region, frameStyle(regions.header), chromeStyle], children: /* @__PURE__ */ jsx33(Header, { arrangement: layout.arrangement, callName, detailsOpen: sheet === "details", onOpenDetails: () => setSheet("details"), ref: nameRef }) }),
|
|
3193
|
+
/* @__PURE__ */ jsx33(Animated12.View, { pointerEvents: chrome.hidden ? "none" : "box-none", style: [styles21.region, frameStyle(regions.dock), chromeStyle], children: /* @__PURE__ */ jsx33(
|
|
2909
3194
|
Dock,
|
|
2910
3195
|
{
|
|
2911
3196
|
arrangement: layout.arrangement,
|
|
@@ -2937,31 +3222,6 @@ function CallFrame({ displayName, callName = "Call", inviteLink, onLeave, onOpen
|
|
|
2937
3222
|
/* @__PURE__ */ jsx33(ChatNotices, { chatVisible: sheet === "chat", onOpenChat: () => setSheet("chat"), sheetOpen: sheet === "people" || sheet === "chat" })
|
|
2938
3223
|
] });
|
|
2939
3224
|
}
|
|
2940
|
-
function useLandscapeChrome(fades) {
|
|
2941
|
-
const [hidden, setHidden] = useState13(false);
|
|
2942
|
-
const [shownAt, setShownAt] = useState13(0);
|
|
2943
|
-
const opacity = useSharedValue5(1);
|
|
2944
|
-
useEffect19(() => {
|
|
2945
|
-
opacity.value = withTiming7(hidden ? 0 : 1, timings.fade);
|
|
2946
|
-
}, [hidden, opacity]);
|
|
2947
|
-
useEffect19(() => {
|
|
2948
|
-
if (!fades) {
|
|
2949
|
-
setHidden(false);
|
|
2950
|
-
return;
|
|
2951
|
-
}
|
|
2952
|
-
const timer = setTimeout(() => setHidden(true), durations.landscapeHide);
|
|
2953
|
-
return () => clearTimeout(timer);
|
|
2954
|
-
}, [fades, shownAt]);
|
|
2955
|
-
const show = useCallback15(() => {
|
|
2956
|
-
setHidden(false);
|
|
2957
|
-
setShownAt(Date.now());
|
|
2958
|
-
}, []);
|
|
2959
|
-
const style = useAnimatedStyle7(() => {
|
|
2960
|
-
"worklet";
|
|
2961
|
-
return { opacity: opacity.value };
|
|
2962
|
-
});
|
|
2963
|
-
return { hidden, show, style };
|
|
2964
|
-
}
|
|
2965
3225
|
function frameStyle(frame) {
|
|
2966
3226
|
return { left: frame.x, top: frame.y, width: frame.width, height: frame.height };
|
|
2967
3227
|
}
|
|
@@ -2973,7 +3233,7 @@ var styles21 = StyleSheet23.create({
|
|
|
2973
3233
|
// src/frame/Chalk.tsx
|
|
2974
3234
|
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
2975
3235
|
function Chalk({ client, colorScheme, onColorSchemeChange, soundsEnabled, onSoundsEnabledChange, ...frame }) {
|
|
2976
|
-
|
|
3236
|
+
useEffect23(() => releaseSounds, []);
|
|
2977
3237
|
return /* @__PURE__ */ jsx34(GestureHandlerRootView, { style: styles22.root, children: /* @__PURE__ */ jsx34(SafeAreaProvider2, { children: /* @__PURE__ */ jsx34(PreferencesProvider, { colorScheme, onColorSchemeChange, onSoundsEnabledChange, soundsEnabled, children: (preferences) => /* @__PURE__ */ jsx34(ThemeProvider, { colorScheme: preferences.colorScheme, children: /* @__PURE__ */ jsx34(DeviceLayoutProvider, { children: /* @__PURE__ */ jsx34(PortalProvider, { children: /* @__PURE__ */ jsx34(ToastProvider, { children: /* @__PURE__ */ jsx34(ChalkProvider, { client, children: /* @__PURE__ */ jsx34(StageViewProvider, { children: /* @__PURE__ */ jsx34(CallFrame, { ...frame }) }) }) }) }) }) }) }) }) });
|
|
2978
3238
|
}
|
|
2979
3239
|
var styles22 = StyleSheet24.create({
|
|
@@ -2994,6 +3254,7 @@ export {
|
|
|
2994
3254
|
buildChalkInviteLink,
|
|
2995
3255
|
extractSpaceInviteFromLink,
|
|
2996
3256
|
getClipboardInviteSuggestion,
|
|
3257
|
+
parseChalkInviteLink,
|
|
2997
3258
|
parseSpaceInviteLink,
|
|
2998
3259
|
useCan,
|
|
2999
3260
|
useChat,
|