@q9labsai/chalk-react-native 4.1.12 → 4.1.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 (90) hide show
  1. package/dist/android.js +2 -2
  2. package/dist/{chunk-FVHH65FR.js → chunk-4NLA35HE.js} +1 -1
  3. package/dist/{chunk-LZ67SXGB.js → chunk-MK6OO4V7.js} +6 -0
  4. package/dist/client.js +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/ios-pad.js +2 -2
  7. package/dist/ios-phone.js +2 -2
  8. package/dist/ios.js +2 -2
  9. package/dist/macos.js +2 -2
  10. package/package.json +4 -4
  11. package/src/callkit/callkit.test.ts +12 -10
  12. package/src/space-client/create-native-space-client.ts +8 -0
  13. package/dist/test-support/test-renderer.d.ts +0 -20
  14. package/dist/test-support/test-renderer.d.ts.map +0 -1
  15. package/src/android/connection-service.test.ts +0 -114
  16. package/src/callkit/resolve-space-callkit-options.test.ts +0 -68
  17. package/src/client.test.ts +0 -12
  18. package/src/clipboard.test.ts +0 -79
  19. package/src/components/Chalk.test.tsx +0 -223
  20. package/src/components/EmbeddedWhiteboard.test.tsx +0 -92
  21. package/src/components/Entrance.test.tsx +0 -26
  22. package/src/components/EntranceView.android.test.tsx +0 -100
  23. package/src/components/EntranceView.ios-pad.test.tsx +0 -160
  24. package/src/components/EntranceView.ios-phone.test.tsx +0 -137
  25. package/src/components/EntranceView.test.tsx +0 -15
  26. package/src/components/ReactionPicker.test.tsx +0 -19
  27. package/src/components/RtcVideoView.test.tsx +0 -12
  28. package/src/components/SpaceView.android.test.tsx +0 -11
  29. package/src/components/SpaceView.ios-pad.test.tsx +0 -11
  30. package/src/components/SpaceView.ios-phone.test.tsx +0 -11
  31. package/src/components/SpaceView.macos.test.tsx +0 -11
  32. package/src/components/SpaceView.shared.test.tsx +0 -116
  33. package/src/components/SpaceView.test.tsx +0 -15
  34. package/src/components/android-connection-service-controller.test.ts +0 -80
  35. package/src/components/episode-diagnostic-render-observer.test.ts +0 -24
  36. package/src/components/logo/Logo.test.tsx +0 -144
  37. package/src/components/native-animation-controller.test.ts +0 -47
  38. package/src/components/native-chat.test.ts +0 -22
  39. package/src/components/native-entrance/entrance-controller-store.test.ts +0 -75
  40. package/src/components/native-media-visibility.test.ts +0 -77
  41. package/src/components/native-space-callkit-controller.test.ts +0 -62
  42. package/src/components/native-space-view/AppearanceSettings.test.tsx +0 -56
  43. package/src/components/native-space-view/ParticipantActionSheet.test.tsx +0 -18
  44. package/src/components/native-space-view/SettingsSheet.test.tsx +0 -17
  45. package/src/components/native-space-view/SpaceActionMenu.test.tsx +0 -126
  46. package/src/components/native-space-view/SpaceBottomDock.android.test.tsx +0 -61
  47. package/src/components/native-space-view/SpaceChatSheet.test.tsx +0 -18
  48. package/src/components/native-space-view/SpaceMoreSheet.test.tsx +0 -15
  49. package/src/components/native-space-view/SpacePanelSheet.test.tsx +0 -15
  50. package/src/components/native-space-view/SpacePeopleSheet.test.tsx +0 -13
  51. package/src/components/native-space-view/SpaceSurfacePrimitives.test.tsx +0 -12
  52. package/src/components/native-space-view/SpaceTopBar.android.test.tsx +0 -50
  53. package/src/components/native-space-view/SpaceWhiteboardSurface.test.tsx +0 -85
  54. package/src/components/native-space-view/diagnostics.test.ts +0 -31
  55. package/src/components/native-space-view/format-space-duration.test.ts +0 -13
  56. package/src/components/native-space-view/native-space-grid-keys.test.ts +0 -11
  57. package/src/components/native-space-view/native-space-page-store.test.ts +0 -23
  58. package/src/components/native-space-view/space-chat-attachments.test.ts +0 -33
  59. package/src/components/native-space-view/space-progressive-surface-helpers.test.ts +0 -24
  60. package/src/components/native-space-view/useSpaceViewController.contract.test.ts +0 -10
  61. package/src/components/native-space-view/useSpaceViewController.test.ts +0 -106
  62. package/src/components/native-space-view/useSpaceViewDerived.test.ts +0 -58
  63. package/src/components/native-space-view/useSpaceViewPanels.controlled.test.ts +0 -40
  64. package/src/components/native-space-view/useSpaceViewPanels.test.ts +0 -73
  65. package/src/components/space-lifecycle.test.ts +0 -19
  66. package/src/context/space-client-context.test.tsx +0 -10
  67. package/src/diagnostics.test.ts +0 -29
  68. package/src/hooks/entrance-preview-store.test.ts +0 -79
  69. package/src/hooks/space-hooks.test.ts +0 -76
  70. package/src/hooks/useLayout.test.ts +0 -16
  71. package/src/invites.test.ts +0 -51
  72. package/src/public-surface.test.ts +0 -26
  73. package/src/runtime.test.ts +0 -83
  74. package/src/space-client/cloudflare-rtk-native.test.ts +0 -118
  75. package/src/space-client/create-native-space-client.test.ts +0 -300
  76. package/src/telemetry.test.ts +0 -143
  77. package/src/test-support/test-renderer.test.ts +0 -9
  78. package/src/test-support/test-renderer.ts +0 -28
  79. package/src/ui/appearance.test.ts +0 -61
  80. package/src/ui/native-appearance-context.controlled.test.tsx +0 -41
  81. package/src/ui/native-appearance-context.test.tsx +0 -14
  82. package/src/ui/native-theme.test.ts +0 -34
  83. package/src/ui/native-theme.test.tsx +0 -14
  84. package/src/ui/participant-avatar.test.ts +0 -29
  85. package/src/ui/theme-tokens.test.ts +0 -14
  86. package/src/ui/theme.test.ts +0 -36
  87. package/src/utils/build-chalk-invite-link.test.ts +0 -12
  88. package/src/utils/ios-simulator.test.ts +0 -96
  89. package/src/utils/native-space-layout.test.ts +0 -170
  90. package/src/whiteboard/embedded-whiteboard-assets.test.ts +0 -31
package/dist/android.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  createNativeSpaceClient,
14
14
  getNativeJourneyContext
15
- } from "./chunk-LZ67SXGB.js";
15
+ } from "./chunk-MK6OO4V7.js";
16
16
 
17
17
  // src/components/Chalk.tsx
18
18
  import { useCallback as useCallback9, useEffect as useEffect9, useMemo as useMemo15, useRef as useRef6, useState as useState10 } from "react";
@@ -362,6 +362,7 @@ function createMediaClient(apiBaseURL, input, fetch, observePeerConnection, jour
362
362
  });
363
363
  return createRTKConnectionMediaClient(client2);
364
364
  }
365
+ const replaceMediaConnection = input.replaceMediaConnection;
365
366
  const client = new CloudflareSFUClient({
366
367
  bootstrap: input.access.media.clientPayload,
367
368
  participantId: subject.participantId,
@@ -374,6 +375,11 @@ function createMediaClient(apiBaseURL, input, fetch, observePeerConnection, jour
374
375
  participantId: subject.participantId,
375
376
  fetch
376
377
  }),
378
+ replaceMediaConnection: replaceMediaConnection ? async () => {
379
+ const replacement = await replaceMediaConnection();
380
+ if (replacement.provider !== "cloudflare_sfu") throw new TypeError("The Cloudflare SFU adapter requires a Cloudflare SFU access grant");
381
+ return replacement.clientPayload;
382
+ } : void 0,
377
383
  peerConnectionFactory: (configuration) => {
378
384
  const connection = new RTCPeerConnection(configuration);
379
385
  observePeerConnection?.(connection);
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createNativeSpaceClient
3
- } from "./chunk-LZ67SXGB.js";
3
+ } from "./chunk-MK6OO4V7.js";
4
4
  export {
5
5
  createNativeSpaceClient
6
6
  };
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
package/dist/ios-pad.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
package/dist/ios-phone.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
package/dist/ios.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
package/dist/macos.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  useSelf,
14
14
  useSpaceClient,
15
15
  useWhiteboard
16
- } from "./chunk-FVHH65FR.js";
16
+ } from "./chunk-4NLA35HE.js";
17
17
  import {
18
18
  THEME_PALETTES,
19
19
  THEME_TEXTURES,
@@ -25,7 +25,7 @@ import {
25
25
  Theme,
26
26
  createNativeTheme
27
27
  } from "./chunk-JB4LNWVP.js";
28
- import "./chunk-LZ67SXGB.js";
28
+ import "./chunk-MK6OO4V7.js";
29
29
  import {
30
30
  extractSpaceInviteFromLink,
31
31
  getClipboardInviteSuggestion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q9labsai/chalk-react-native",
3
- "version": "4.1.12",
3
+ "version": "4.1.13",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -150,9 +150,9 @@
150
150
  "registry": "https://registry.npmjs.org/"
151
151
  },
152
152
  "dependencies": {
153
- "@q9labsai/chalk-client": "^4.1.12",
154
- "@q9labsai/chalk-whiteboard": "^4.1.12",
155
- "@q9labsai/facehash": "^4.1.12"
153
+ "@q9labsai/chalk-client": "^4.1.13",
154
+ "@q9labsai/chalk-whiteboard": "^4.1.13",
155
+ "@q9labsai/facehash": "^4.1.13"
156
156
  },
157
157
  "devDependencies": {
158
158
  "@types/node": "^26.2.0",
@@ -2,23 +2,17 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
 
3
3
  const addListener = vi.fn();
4
4
  const configure = vi.fn(async () => ({ isSupported: true }));
5
- const endAllCalls = vi.fn(async () => undefined);
6
5
  const endCall = vi.fn(async () => undefined);
7
6
  const reportConnected = vi.fn(async () => undefined);
8
- const reportIncomingCall = vi.fn(async () => ({ callUUID: "incoming-uuid" }));
9
7
  const startCall = vi.fn(async () => ({ callUUID: "outgoing-uuid" }));
10
- const updateCall = vi.fn(async () => undefined);
11
8
 
12
9
  const nativeModule = {
13
10
  configure,
14
- endAllCalls,
15
11
  endCall,
16
12
  eventName: "ChalkCallKitEvent",
17
13
  isSupported: true,
18
14
  reportConnected,
19
- reportIncomingCall,
20
15
  startCall,
21
- updateCall,
22
16
  };
23
17
 
24
18
  const eventEmitter = {
@@ -45,12 +39,9 @@ describe("callKit", () => {
45
39
  nativeModule.isSupported = true;
46
40
  addListener.mockReset();
47
41
  configure.mockClear();
48
- endAllCalls.mockClear();
49
42
  endCall.mockClear();
50
43
  reportConnected.mockClear();
51
- reportIncomingCall.mockClear();
52
44
  startCall.mockClear();
53
- updateCall.mockClear();
54
45
  });
55
46
 
56
47
  it("uses the native event emitter when the iOS module is available", async () => {
@@ -79,17 +70,28 @@ describe("callKit", () => {
79
70
  expect(startCall).not.toHaveBeenCalled();
80
71
  });
81
72
 
82
- it("passes configuration through to the native bridge", async () => {
73
+ it("forwards controller-facing calls and preserves native failures", async () => {
83
74
  const { callKit } = await import("./callkit");
75
+ const callOptions = { callUUID: "call-uuid", displayName: "Space", handle: "space-123", hasVideo: true };
84
76
 
85
77
  await callKit.configure({
86
78
  appName: "Chalk",
87
79
  includesCallsInRecents: false,
88
80
  });
81
+ await expect(callKit.startCall(callOptions)).resolves.toEqual({ callUUID: "outgoing-uuid" });
82
+ await callKit.reportConnected({ callUUID: "outgoing-uuid" });
83
+ await callKit.endCall({ callUUID: "outgoing-uuid", reason: "remoteEnded" });
89
84
 
90
85
  expect(configure).toHaveBeenCalledWith({
91
86
  appName: "Chalk",
92
87
  includesCallsInRecents: false,
93
88
  });
89
+ expect(startCall).toHaveBeenCalledWith(callOptions);
90
+ expect(reportConnected).toHaveBeenCalledWith({ callUUID: "outgoing-uuid" });
91
+ expect(endCall).toHaveBeenCalledWith({ callUUID: "outgoing-uuid", reason: "remoteEnded" });
92
+
93
+ const nativeFailure = new Error("CallKit unavailable");
94
+ startCall.mockRejectedValueOnce(nativeFailure);
95
+ await expect(callKit.startCall(callOptions)).rejects.toBe(nativeFailure);
94
96
  });
95
97
  });
@@ -144,6 +144,7 @@ function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch:
144
144
  });
145
145
  return createRTKConnectionMediaClient(client);
146
146
  }
147
+ const replaceMediaConnection = input.replaceMediaConnection;
147
148
  const client = new CloudflareSFUClient({
148
149
  bootstrap: input.access.media.clientPayload,
149
150
  participantId: subject.participantId,
@@ -156,6 +157,13 @@ function createMediaClient(apiBaseURL: string, input: MediaFactoryInput, fetch:
156
157
  participantId: subject.participantId,
157
158
  fetch,
158
159
  }),
160
+ replaceMediaConnection: replaceMediaConnection
161
+ ? async () => {
162
+ const replacement = await replaceMediaConnection();
163
+ if (replacement.provider !== "cloudflare_sfu") throw new TypeError("The Cloudflare SFU adapter requires a Cloudflare SFU access grant");
164
+ return replacement.clientPayload;
165
+ }
166
+ : undefined,
159
167
  peerConnectionFactory: (configuration) => {
160
168
  const connection = new RTCPeerConnection(configuration);
161
169
  observePeerConnection?.(connection as unknown as RtcPeerConnection);
@@ -1,20 +0,0 @@
1
- import type { ComponentType, ReactNode } from "react";
2
- type RenderHookOptions<Props> = {
3
- readonly initialProps?: Props;
4
- readonly wrapper?: ComponentType<{
5
- readonly children?: ReactNode;
6
- }>;
7
- };
8
- type RenderHookResult<Result, Props> = {
9
- readonly result: {
10
- readonly current: Result;
11
- };
12
- readonly rerender: (props?: Props) => void;
13
- readonly unmount: () => void;
14
- };
15
- type RenderHook = <Result, Props = undefined>(callback: (props: Props) => Result, options?: RenderHookOptions<Props>) => RenderHookResult<Result, Props>;
16
- type Act = (callback: () => void | Promise<void>) => void | Promise<void>;
17
- type WaitFor = (callback: () => void | Promise<void>) => Promise<void>;
18
- export declare const act: Act, renderHook: RenderHook, waitFor: WaitFor;
19
- export {};
20
- //# sourceMappingURL=test-renderer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-renderer.d.ts","sourceRoot":"","sources":["../../src/test-support/test-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,KAAK,iBAAiB,CAAC,KAAK,IAAI;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACrE,CAAC;AAEF,KAAK,gBAAgB,CAAC,MAAM,EAAE,KAAK,IAAI;IACrC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACzJ,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC1E,KAAK,OAAO,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQvE,eAAO,MAAQ,GAAG,OAAE,UAAU,cAAE,OAAO,SAAmB,CAAC"}
@@ -1,114 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
-
3
- const nativeModule = {
4
- addListener: vi.fn(),
5
- endCall: vi.fn(async () => true),
6
- isSupported: vi.fn(async () => true),
7
- registerPhoneAccount: vi.fn(async () => true),
8
- removeListeners: vi.fn(),
9
- setActive: vi.fn(async () => true),
10
- startCall: vi.fn(async () => true),
11
- };
12
-
13
- const subscriptions = new Map<string, (payload: unknown) => void>();
14
- const platform = { OS: "android" };
15
-
16
- class MockNativeEventEmitter {
17
- addListener(eventName: string, listener: (payload: unknown) => void) {
18
- subscriptions.set(eventName, listener);
19
- return {
20
- remove: () => {
21
- subscriptions.delete(eventName);
22
- },
23
- };
24
- }
25
- }
26
-
27
- vi.mock("react-native", () => ({
28
- NativeEventEmitter: MockNativeEventEmitter,
29
- NativeModules: {
30
- ChalkAndroidConnectionService: nativeModule,
31
- },
32
- Platform: platform,
33
- }));
34
-
35
- describe("android connection service bridge", () => {
36
- beforeEach(() => {
37
- vi.resetModules();
38
- vi.clearAllMocks();
39
- subscriptions.clear();
40
- platform.OS = "android";
41
- });
42
-
43
- it("no-ops when Android native support is unavailable", async () => {
44
- platform.OS = "ios";
45
-
46
- const { addAndroidConnectionServiceListener, ensureAndroidConnectionServiceRegistered, endAndroidConnectionServiceCall, isAndroidConnectionServiceSupported, setAndroidConnectionServiceActive, startAndroidConnectionServiceCall } = await import("./connection-service");
47
-
48
- expect(await isAndroidConnectionServiceSupported()).toBe(false);
49
- expect(await ensureAndroidConnectionServiceRegistered()).toBe(false);
50
- expect(
51
- await startAndroidConnectionServiceCall({
52
- callId: "space-1:1",
53
- displayName: "Host",
54
- spaceId: "space-1",
55
- spaceName: "Daily Standup",
56
- }),
57
- ).toBe(false);
58
- expect(await setAndroidConnectionServiceActive("space-1:1")).toBe(false);
59
- expect(await endAndroidConnectionServiceCall("space-1:1")).toBe(false);
60
-
61
- const unsubscribe = addAndroidConnectionServiceListener(() => {
62
- throw new Error("listener should not be called on iOS");
63
- });
64
- unsubscribe();
65
-
66
- expect(nativeModule.isSupported).not.toHaveBeenCalled();
67
- expect(nativeModule.registerPhoneAccount).not.toHaveBeenCalled();
68
- expect(nativeModule.startCall).not.toHaveBeenCalled();
69
- expect(nativeModule.setActive).not.toHaveBeenCalled();
70
- expect(nativeModule.endCall).not.toHaveBeenCalled();
71
- });
72
-
73
- it("passes through Android native module calls and emits disconnect events", async () => {
74
- const { addAndroidConnectionServiceListener, ensureAndroidConnectionServiceRegistered, endAndroidConnectionServiceCall, isAndroidConnectionServiceSupported, setAndroidConnectionServiceActive, startAndroidConnectionServiceCall } = await import("./connection-service");
75
-
76
- expect(await isAndroidConnectionServiceSupported()).toBe(true);
77
- expect(await ensureAndroidConnectionServiceRegistered()).toBe(true);
78
- expect(
79
- await startAndroidConnectionServiceCall({
80
- callId: "space-1:2",
81
- displayName: "Guest",
82
- hasVideo: false,
83
- spaceId: "space-1",
84
- spaceName: "Board Review",
85
- }),
86
- ).toBe(true);
87
- expect(await setAndroidConnectionServiceActive("space-1:2")).toBe(true);
88
- expect(await endAndroidConnectionServiceCall("space-1:2", { reason: "remote", label: "Space ended" })).toBe(true);
89
-
90
- const listener = vi.fn();
91
- const unsubscribe = addAndroidConnectionServiceListener(listener);
92
- const disconnectPayload = {
93
- callId: "space-1:2",
94
- reason: "local",
95
- type: "disconnect",
96
- };
97
-
98
- subscriptions.get("ChalkAndroidConnectionServiceEvent")?.(disconnectPayload);
99
- unsubscribe();
100
-
101
- expect(nativeModule.isSupported).toHaveBeenCalledTimes(1);
102
- expect(nativeModule.registerPhoneAccount).toHaveBeenCalledTimes(1);
103
- expect(nativeModule.startCall).toHaveBeenCalledWith({
104
- callId: "space-1:2",
105
- displayName: "Guest",
106
- hasVideo: false,
107
- spaceId: "space-1",
108
- spaceName: "Board Review",
109
- });
110
- expect(nativeModule.setActive).toHaveBeenCalledWith("space-1:2");
111
- expect(nativeModule.endCall).toHaveBeenCalledWith("space-1:2", "remote", "Space ended");
112
- expect(listener).toHaveBeenCalledWith(disconnectPayload);
113
- });
114
- });
@@ -1,68 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { resolveSpaceCallKitOptions } from "./resolve-space-callkit-options";
3
-
4
- describe("resolveSpaceCallKitOptions", () => {
5
- it("returns null when CallKit is disabled", () => {
6
- expect(
7
- resolveSpaceCallKitOptions({
8
- callKit: false,
9
- hasVideo: true,
10
- spaceId: "space-123",
11
- spaceName: "Design Review",
12
- }),
13
- ).toBeNull();
14
- });
15
-
16
- it("fills sensible defaults for enabled Spaces", () => {
17
- expect(
18
- resolveSpaceCallKitOptions({
19
- callKit: true,
20
- hasVideo: true,
21
- spaceId: "space-123",
22
- spaceName: "Design Review",
23
- }),
24
- ).toEqual({
25
- appName: "Chalk",
26
- displayName: "Design Review",
27
- handle: "space-123",
28
- handleType: "generic",
29
- hasVideo: true,
30
- includesCallsInRecents: false,
31
- maximumCallGroups: 1,
32
- maximumCallsPerCallGroup: 1,
33
- iconTemplateImageName: undefined,
34
- ringtoneSound: undefined,
35
- });
36
- });
37
-
38
- it("prefers explicit overrides from the caller", () => {
39
- expect(
40
- resolveSpaceCallKitOptions({
41
- callKit: {
42
- appName: "Chalk Meet",
43
- displayName: "Board Space",
44
- handle: "board-space",
45
- handleType: "emailAddress",
46
- hasVideo: false,
47
- includesCallsInRecents: true,
48
- maximumCallGroups: 2,
49
- maximumCallsPerCallGroup: 3,
50
- ringtoneSound: "ring.caf",
51
- },
52
- hasVideo: true,
53
- spaceId: "space-123",
54
- }),
55
- ).toEqual({
56
- appName: "Chalk Meet",
57
- displayName: "Board Space",
58
- handle: "board-space",
59
- handleType: "emailAddress",
60
- hasVideo: false,
61
- includesCallsInRecents: true,
62
- maximumCallGroups: 2,
63
- maximumCallsPerCallGroup: 3,
64
- iconTemplateImageName: undefined,
65
- ringtoneSound: "ring.caf",
66
- });
67
- });
68
- });
@@ -1,12 +0,0 @@
1
- import type { GetAccess, SpaceClient } from "@q9labsai/chalk-client";
2
- import { expectTypeOf, test } from "vitest";
3
-
4
- import type { NativeSpaceClientOptions } from "./client";
5
-
6
- test("the native client subpath exposes the advanced-construction contract", () => {
7
- expectTypeOf<NativeSpaceClientOptions>().toMatchTypeOf<{
8
- readonly space: string;
9
- readonly getAccess: GetAccess;
10
- }>();
11
- expectTypeOf<typeof import("./client").createNativeSpaceClient>().returns.toEqualTypeOf<SpaceClient>();
12
- });
@@ -1,79 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { createClipboardTextStore } from "./clipboard-store";
3
-
4
- vi.mock("react-native", () => ({
5
- AppState: { addEventListener: vi.fn(() => ({ remove: vi.fn() })) },
6
- NativeModules: { ChalkRuntimeInfo: { isSimulator: false } },
7
- Platform: { OS: "ios" },
8
- }));
9
-
10
- describe("clipboard invite suggestion hook", () => {
11
- it("exposes the extracted clipboard suggestion hook", async () => {
12
- const { useClipboardInviteSuggestion } = await import("./clipboard");
13
-
14
- expect(typeof useClipboardInviteSuggestion).toBe("function");
15
- });
16
- });
17
-
18
- describe("createClipboardTextStore", () => {
19
- it("refreshes on subscription and active app-state events, then stops after unsubscribe", async () => {
20
- let appStateListener: ((nextState: string) => void) | undefined;
21
- const removeAppStateListener = vi.fn();
22
- const clipboard = {
23
- hasStringAsync: vi.fn().mockResolvedValue(true),
24
- getStringAsync: vi.fn().mockResolvedValue("chalk invite"),
25
- };
26
- const store = createClipboardTextStore({
27
- clipboard,
28
- shouldReadClipboard: true,
29
- subscribeToAppState: (listener) => {
30
- appStateListener = listener;
31
- return { remove: removeAppStateListener };
32
- },
33
- });
34
- const listener = vi.fn();
35
-
36
- const unsubscribe = store.subscribe(listener);
37
- await Promise.resolve();
38
- await Promise.resolve();
39
-
40
- expect(store.getSnapshot()).toBe("chalk invite");
41
- expect(listener).toHaveBeenCalledOnce();
42
-
43
- appStateListener?.("active");
44
- await Promise.resolve();
45
- await Promise.resolve();
46
-
47
- expect(clipboard.hasStringAsync).toHaveBeenCalledTimes(2);
48
-
49
- unsubscribe();
50
- expect(removeAppStateListener).toHaveBeenCalledOnce();
51
- appStateListener?.("active");
52
- await Promise.resolve();
53
- await Promise.resolve();
54
-
55
- expect(clipboard.hasStringAsync).toHaveBeenCalledTimes(2);
56
- });
57
-
58
- it("does not read the clipboard when the platform policy disables automatic reads", async () => {
59
- const clipboard = {
60
- hasStringAsync: vi.fn(),
61
- getStringAsync: vi.fn(),
62
- };
63
- const subscribeToAppState = vi.fn();
64
- const store = createClipboardTextStore({
65
- clipboard,
66
- shouldReadClipboard: false,
67
- subscribeToAppState,
68
- });
69
-
70
- const unsubscribe = store.subscribe(vi.fn());
71
- await Promise.resolve();
72
-
73
- expect(store.getSnapshot()).toBeNull();
74
- expect(clipboard.hasStringAsync).not.toHaveBeenCalled();
75
- expect(subscribeToAppState).not.toHaveBeenCalled();
76
-
77
- unsubscribe();
78
- });
79
- });