@peers-app/peers-ui 0.25.2 → 0.25.4

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 (180) hide show
  1. package/README.md +2 -1
  2. package/dist/components/markdown-editor/mention-node.d.ts +4 -0
  3. package/dist/components/markdown-editor/mention-node.js +4 -1
  4. package/dist/components/responsive-section-nav.d.ts +34 -0
  5. package/dist/components/responsive-section-nav.js +19 -0
  6. package/dist/components/responsive-section-nav.test.d.ts +1 -0
  7. package/dist/components/responsive-section-nav.test.js +45 -0
  8. package/dist/components/router.d.ts +2 -3
  9. package/dist/components/router.js +6 -9
  10. package/dist/globals-hash.test.d.ts +1 -0
  11. package/dist/globals-hash.test.js +16 -0
  12. package/dist/globals.d.ts +19 -0
  13. package/dist/globals.js +51 -12
  14. package/dist/hooks/use-host-contract.d.ts +18 -0
  15. package/dist/hooks/use-host-contract.js +53 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/peers-services-registration.d.ts +1 -5
  19. package/dist/peers-services-registration.js +6 -16
  20. package/dist/root-layout/root-layout-host.js +7 -4
  21. package/dist/root-layout/root-layout-host.test.js +3 -6
  22. package/dist/screens/account/account-screen.d.ts +1 -0
  23. package/dist/screens/account/account-screen.js +29 -53
  24. package/dist/screens/account/account-screen.test.d.ts +1 -0
  25. package/dist/screens/account/account-screen.test.js +47 -0
  26. package/dist/screens/contacts/contact-details.js +2 -23
  27. package/dist/screens/contacts/contact-list.d.ts +24 -1
  28. package/dist/screens/contacts/contact-list.js +128 -143
  29. package/dist/screens/contacts/contact-list.test.d.ts +1 -0
  30. package/dist/screens/contacts/contact-list.test.js +48 -0
  31. package/dist/screens/contacts/index.d.ts +0 -2
  32. package/dist/screens/contacts/index.js +0 -3
  33. package/dist/screens/device-pairing/device-pairing.js +17 -16
  34. package/dist/screens/device-pairing/device-pairing.test.js +4 -9
  35. package/dist/screens/device-pairing/identity-ipc.d.ts +11 -0
  36. package/dist/screens/device-pairing/identity-ipc.js +20 -0
  37. package/dist/screens/device-pairing/use-device-pairing-state.d.ts +2 -2
  38. package/dist/screens/device-pairing/use-device-pairing-state.js +7 -25
  39. package/dist/screens/devices/devices-list.d.ts +18 -0
  40. package/dist/screens/devices/devices-list.js +173 -0
  41. package/dist/screens/devices/devices-list.test.d.ts +1 -0
  42. package/dist/screens/devices/devices-list.test.js +53 -0
  43. package/dist/screens/devices/index.d.ts +1 -0
  44. package/dist/screens/devices/index.js +5 -0
  45. package/dist/screens/groups/group-details.d.ts +1 -0
  46. package/dist/screens/groups/group-details.js +4 -63
  47. package/dist/screens/groups/group-invite-panel.js +2 -2
  48. package/dist/screens/groups/group-list.d.ts +18 -1
  49. package/dist/screens/groups/group-list.js +107 -136
  50. package/dist/screens/groups/group-list.test.d.ts +1 -0
  51. package/dist/screens/groups/group-list.test.js +38 -0
  52. package/dist/screens/groups/group-members.d.ts +1 -0
  53. package/dist/screens/groups/group-members.js +2 -1
  54. package/dist/screens/groups/index.d.ts +0 -3
  55. package/dist/screens/groups/index.js +0 -4
  56. package/dist/screens/identity/identity-routes.d.ts +107 -0
  57. package/dist/screens/identity/identity-routes.js +245 -0
  58. package/dist/screens/identity/identity-routes.test.d.ts +1 -0
  59. package/dist/screens/identity/identity-routes.test.js +51 -0
  60. package/dist/screens/identity/identity-screen.d.ts +9 -0
  61. package/dist/screens/identity/identity-screen.js +143 -0
  62. package/dist/screens/identity/identity-screen.test.d.ts +1 -0
  63. package/dist/screens/identity/identity-screen.test.js +103 -0
  64. package/dist/screens/identity/index.d.ts +2 -0
  65. package/dist/screens/identity/index.js +6 -0
  66. package/dist/screens/identity/invite-contact-panel.d.ts +4 -0
  67. package/dist/screens/identity/invite-contact-panel.js +30 -0
  68. package/dist/screens/identity/profile-invite.d.ts +7 -0
  69. package/dist/screens/identity/profile-invite.js +62 -0
  70. package/dist/screens/invites/accept-invite.js +44 -2
  71. package/dist/screens/invites/accept-invite.test.d.ts +1 -0
  72. package/dist/screens/invites/accept-invite.test.js +103 -0
  73. package/dist/screens/invites/activity-view.d.ts +24 -0
  74. package/dist/screens/invites/activity-view.js +64 -0
  75. package/dist/screens/invites/activity-view.test.d.ts +1 -0
  76. package/dist/screens/invites/activity-view.test.js +108 -0
  77. package/dist/screens/invites/index.d.ts +1 -2
  78. package/dist/screens/invites/index.js +1 -3
  79. package/dist/screens/invites/invite-capture.d.ts +0 -2
  80. package/dist/screens/invites/invite-capture.js +1 -3
  81. package/dist/screens/invites/invite-classify.test.d.ts +1 -0
  82. package/dist/screens/invites/invite-classify.test.js +115 -0
  83. package/dist/screens/invites/invites-ipc.d.ts +1 -1
  84. package/dist/screens/invites/invites-ipc.js +5 -45
  85. package/dist/screens/invites/pending-invites-list.d.ts +35 -16
  86. package/dist/screens/invites/pending-invites-list.js +75 -30
  87. package/dist/screens/network-viewer/network-viewer-ipc.js +4 -59
  88. package/dist/screens/search/global-search.d.ts +1 -0
  89. package/dist/screens/search/global-search.js +2 -1
  90. package/dist/screens/settings/settings-page.js +25 -58
  91. package/dist/screens/setup-user.js +5 -5
  92. package/dist/screens/tools/tool-access-ipc.d.ts +2 -0
  93. package/dist/screens/tools/tool-access-ipc.js +8 -55
  94. package/dist/screens/welcome-modal.js +3 -2
  95. package/dist/system-apps/identity.app.d.ts +3 -0
  96. package/dist/system-apps/identity.app.js +10 -0
  97. package/dist/system-apps/index.d.ts +1 -4
  98. package/dist/system-apps/index.js +5 -17
  99. package/dist/tabs-layout/network-status-indicator.js +10 -3
  100. package/dist/tabs-layout/network-status-indicator.test.js +15 -0
  101. package/dist/tabs-layout/tabs-layout.js +3 -1
  102. package/dist/tabs-layout/tabs-state.d.ts +79 -1
  103. package/dist/tabs-layout/tabs-state.js +256 -79
  104. package/dist/tabs-layout/tabs-state.test.d.ts +1 -0
  105. package/dist/tabs-layout/tabs-state.test.js +110 -0
  106. package/package.json +3 -3
  107. package/src/components/markdown-editor/mention-node.ts +5 -1
  108. package/src/components/responsive-section-nav.test.tsx +88 -0
  109. package/src/components/responsive-section-nav.tsx +92 -0
  110. package/src/components/router.tsx +6 -9
  111. package/src/globals-hash.test.ts +19 -0
  112. package/src/globals.tsx +53 -13
  113. package/src/hooks/use-host-contract.ts +75 -0
  114. package/src/index.tsx +1 -0
  115. package/src/peers-services-registration.ts +6 -17
  116. package/src/root-layout/root-layout-host.test.tsx +4 -7
  117. package/src/root-layout/root-layout-host.tsx +9 -11
  118. package/src/screens/account/account-screen.test.tsx +61 -0
  119. package/src/screens/account/account-screen.tsx +116 -95
  120. package/src/screens/contacts/contact-details.tsx +4 -26
  121. package/src/screens/contacts/contact-list.test.tsx +59 -0
  122. package/src/screens/contacts/contact-list.tsx +246 -260
  123. package/src/screens/contacts/index.ts +0 -4
  124. package/src/screens/device-pairing/device-pairing.test.tsx +7 -9
  125. package/src/screens/device-pairing/device-pairing.tsx +19 -23
  126. package/src/screens/device-pairing/identity-ipc.ts +25 -0
  127. package/src/screens/device-pairing/use-device-pairing-state.ts +10 -33
  128. package/src/screens/devices/devices-list.test.tsx +68 -0
  129. package/src/screens/devices/devices-list.tsx +361 -0
  130. package/src/screens/devices/index.ts +1 -0
  131. package/src/screens/groups/group-details.tsx +8 -142
  132. package/src/screens/groups/group-invite-panel.tsx +2 -7
  133. package/src/screens/groups/group-list.test.tsx +44 -0
  134. package/src/screens/groups/group-list.tsx +227 -288
  135. package/src/screens/groups/group-members.tsx +3 -2
  136. package/src/screens/groups/index.ts +0 -5
  137. package/src/screens/identity/identity-routes.test.ts +70 -0
  138. package/src/screens/identity/identity-routes.ts +301 -0
  139. package/src/screens/identity/identity-screen.test.tsx +138 -0
  140. package/src/screens/identity/identity-screen.tsx +282 -0
  141. package/src/screens/identity/index.ts +2 -0
  142. package/src/screens/identity/invite-contact-panel.tsx +45 -0
  143. package/src/screens/identity/profile-invite.tsx +93 -0
  144. package/src/screens/invites/accept-invite.test.tsx +115 -0
  145. package/src/screens/invites/accept-invite.tsx +50 -3
  146. package/src/screens/invites/activity-view.test.tsx +127 -0
  147. package/src/screens/invites/activity-view.tsx +162 -0
  148. package/src/screens/invites/index.ts +1 -4
  149. package/src/screens/invites/invite-capture.ts +0 -3
  150. package/src/screens/invites/invite-classify.test.ts +129 -0
  151. package/src/screens/invites/invites-ipc.ts +6 -55
  152. package/src/screens/invites/pending-invites-list.tsx +94 -62
  153. package/src/screens/network-viewer/network-viewer-ipc.ts +8 -82
  154. package/src/screens/search/global-search.tsx +2 -1
  155. package/src/screens/settings/settings-page.tsx +53 -126
  156. package/src/screens/setup-user.tsx +5 -6
  157. package/src/screens/tools/tool-access-ipc.ts +13 -74
  158. package/src/screens/welcome-modal.tsx +3 -3
  159. package/src/system-apps/identity.app.ts +9 -0
  160. package/src/system-apps/index.ts +3 -12
  161. package/src/tabs-layout/network-status-indicator.test.tsx +22 -0
  162. package/src/tabs-layout/network-status-indicator.tsx +31 -0
  163. package/src/tabs-layout/tabs-layout.tsx +7 -1
  164. package/src/tabs-layout/tabs-state.test.ts +152 -0
  165. package/src/tabs-layout/tabs-state.ts +300 -83
  166. package/dist/screens/invites/invites-screen.d.ts +0 -9
  167. package/dist/screens/invites/invites-screen.js +0 -36
  168. package/dist/system-apps/account.app.d.ts +0 -2
  169. package/dist/system-apps/account.app.js +0 -8
  170. package/dist/system-apps/contacts.app.d.ts +0 -2
  171. package/dist/system-apps/contacts.app.js +0 -9
  172. package/dist/system-apps/groups.app.d.ts +0 -2
  173. package/dist/system-apps/groups.app.js +0 -9
  174. package/dist/system-apps/invites.app.d.ts +0 -2
  175. package/dist/system-apps/invites.app.js +0 -9
  176. package/src/screens/invites/invites-screen.tsx +0 -78
  177. package/src/system-apps/account.app.ts +0 -7
  178. package/src/system-apps/contacts.app.ts +0 -8
  179. package/src/system-apps/groups.app.ts +0 -8
  180. package/src/system-apps/invites.app.ts +0 -8
@@ -3,57 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvitesConsumer = getInvitesConsumer;
4
4
  exports.inviteTools = inviteTools;
5
5
  const peers_sdk_1 = require("@peers-app/peers-sdk");
6
- const HOST_TRANSPORT_TIMEOUT_MS = 10_000;
7
- let cached;
8
- let pending;
9
- (0, peers_sdk_1.subscribeHostContractTransport)((transport) => {
10
- if (cached && cached.transport !== transport) {
11
- cached.consumer.dispose();
12
- cached = undefined;
13
- pending = undefined;
14
- }
15
- }, { emitCurrent: false });
16
- async function load(transport) {
17
- const userContext = await (0, peers_sdk_1.getUserContext)();
18
- const consumer = (0, peers_sdk_1.createContractConsumer)((0, peers_sdk_1.getInvitesContractDefinition)(), transport, {
19
- dataContextId: userContext.userId,
20
- });
21
- try {
22
- await consumer.loadingPromise;
23
- if ((0, peers_sdk_1.getHostContractTransport)() !== transport) {
24
- consumer.dispose();
25
- return getInvitesConsumer();
26
- }
27
- cached = { transport, consumer };
28
- return consumer;
29
- }
30
- catch (error) {
31
- consumer.dispose();
32
- throw error;
33
- }
34
- }
6
+ const invites = (0, peers_sdk_1.hostContractConsumer)((0, peers_sdk_1.getInvitesContractDefinition)(), {
7
+ dataContextId: async () => (await (0, peers_sdk_1.getUserContext)()).userId,
8
+ });
35
9
  /**
36
10
  * Return the typed local-host consumer for the System Invites contract.
37
11
  *
38
12
  * The consumer is cached per host transport and rebuilt if the transport is replaced
39
- * (e.g. after a socket reconnect).
13
+ * (for example after a socket reconnect).
40
14
  */
41
15
  async function getInvitesConsumer() {
42
- const transport = (0, peers_sdk_1.getHostContractTransport)() ??
43
- (await (0, peers_sdk_1.waitForHostContractTransport)({ timeoutMs: HOST_TRANSPORT_TIMEOUT_MS }));
44
- if (cached?.transport === transport) {
45
- return cached.consumer;
46
- }
47
- if (pending) {
48
- return pending;
49
- }
50
- pending = load(transport);
51
- try {
52
- return await pending;
53
- }
54
- finally {
55
- pending = undefined;
56
- }
16
+ return invites.get();
57
17
  }
58
18
  /** Shorthand for `(await getInvitesConsumer()).tools`. */
59
19
  async function inviteTools() {
@@ -1,29 +1,48 @@
1
1
  import { type IInvite, type InviteStatus } from "@peers-app/peers-sdk";
2
- /** Props for {@link PendingInvitesList}. */
3
- export interface PendingInvitesListProps {
4
- /** Only show rows of this type. */
5
- type?: IInvite["type"];
6
- /** Only show rows for this group. */
7
- groupId?: string;
8
- /** Statuses to include; defaults to pending only. */
9
- statuses?: InviteStatus[];
10
- /** Hide the section entirely when there is nothing to show. */
11
- hideWhenEmpty?: boolean;
12
- title?: string;
2
+ /** Filtered invite rows plus whether any non-pending row exists for the same type and group. */
3
+ export interface IInviteRowQuery {
4
+ /** Rows matching the status filter, newest first. */
5
+ rows: IInvite[];
6
+ /** True when at least one matching invite is not pending. */
7
+ hasHistory: boolean;
13
8
  }
14
- /** Subscribe to the personal `Invites` table and return rows matching the filter, newest first. */
9
+ /**
10
+ * Subscribe to the personal `Invites` table.
11
+ *
12
+ * @param filter Type, group, and statuses to include. Statuses default to pending.
13
+ * @returns Matching rows and whether any non-pending row exists, or `undefined` while loading.
14
+ */
15
15
  export declare function useInviteRows(filter: {
16
16
  type?: IInvite["type"];
17
17
  groupId?: string;
18
18
  statuses?: InviteStatus[];
19
- }): IInvite[] | undefined;
19
+ }): IInviteRowQuery | undefined;
20
20
  /** Human summary of what a row is, from the local user's point of view. */
21
21
  export declare function describeInviteRow(row: IInvite): {
22
22
  title: string;
23
23
  detail: string;
24
24
  };
25
+ /** Which Activity bucket a row belongs in. */
26
+ export type InviteBucket = "attention" | "waiting" | "history";
27
+ /**
28
+ * Group an invite by what the signed-in user can do with it.
29
+ *
30
+ * Pending rows that need a decision are `attention`. Pending rows waiting on
31
+ * someone else, including links the user issued, are `waiting`.
32
+ *
33
+ * @param row - Invite row from the personal Invites table.
34
+ */
35
+ export declare function classifyInvite(row: IInvite): InviteBucket;
36
+ /** Action that the local user can take on an Activity row. */
37
+ export type InviteRowAction = "accept" | "decline" | "approve" | "deny" | "revoke";
25
38
  /**
26
- * Live list of invite rows with the actions each one supports. Subscribes to the `Invites`
27
- * table directly, so it updates when replies arrive on any of the user's devices.
39
+ * Return actions that are valid from the local user's perspective.
40
+ *
41
+ * Inbound rows with `recipientUserId` were initiated locally and are waiting
42
+ * for that recipient. Actionable profile requests and join requests omit it.
28
43
  */
29
- export declare function PendingInvitesList(props: PendingInvitesListProps): import("react/jsx-runtime").JSX.Element | null;
44
+ export declare function actionsForInvite(row: IInvite): InviteRowAction[];
45
+ /** One invite row and the actions its direction and status allow. */
46
+ export declare function InviteRow({ row }: {
47
+ row: IInvite;
48
+ }): import("react/jsx-runtime").JSX.Element;
@@ -2,14 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useInviteRows = useInviteRows;
4
4
  exports.describeInviteRow = describeInviteRow;
5
- exports.PendingInvitesList = PendingInvitesList;
5
+ exports.classifyInvite = classifyInvite;
6
+ exports.actionsForInvite = actionsForInvite;
7
+ exports.InviteRow = InviteRow;
6
8
  const jsx_runtime_1 = require("react/jsx-runtime");
7
9
  const peers_sdk_1 = require("@peers-app/peers-sdk");
8
10
  const react_1 = require("react");
9
11
  const invites_ipc_1 = require("./invites-ipc");
10
- /** Subscribe to the personal `Invites` table and return rows matching the filter, newest first. */
12
+ /**
13
+ * Subscribe to the personal `Invites` table.
14
+ *
15
+ * @param filter Type, group, and statuses to include. Statuses default to pending.
16
+ * @returns Matching rows and whether any non-pending row exists, or `undefined` while loading.
17
+ */
11
18
  function useInviteRows(filter) {
12
- const [rows, setRows] = (0, react_1.useState)(undefined);
19
+ const [query, setQuery] = (0, react_1.useState)(undefined);
13
20
  const statuses = filter.statuses ?? ["pending"];
14
21
  const statusKey = statuses.join(",");
15
22
  const refresh = (0, react_1.useCallback)(async () => {
@@ -20,9 +27,12 @@ function useInviteRows(filter) {
20
27
  ...(filter.groupId ? { groupId: filter.groupId } : {}),
21
28
  });
22
29
  const wanted = new Set(statusKey.split(","));
23
- setRows(all
24
- .filter((row) => wanted.has(row.status))
25
- .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()));
30
+ setQuery({
31
+ rows: all
32
+ .filter((row) => wanted.has(row.status))
33
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()),
34
+ hasHistory: all.some((row) => row.status !== "pending"),
35
+ });
26
36
  }, [filter.type, filter.groupId, statusKey]);
27
37
  (0, react_1.useEffect)(() => {
28
38
  let disposed = false;
@@ -42,7 +52,7 @@ function useInviteRows(filter) {
42
52
  dispose?.();
43
53
  };
44
54
  }, [refresh]);
45
- return rows;
55
+ return query;
46
56
  }
47
57
  function counterpartLabel(row) {
48
58
  return row.counterpart?.displayName || row.counterpart?.userId || "Someone";
@@ -52,8 +62,20 @@ function describeInviteRow(row) {
52
62
  const who = counterpartLabel(row);
53
63
  const role = row.role !== undefined ? (0, peers_sdk_1.getRoleLabel)(row.role) : undefined;
54
64
  const group = row.groupName ?? "a group";
65
+ if (row.type === "device") {
66
+ return {
67
+ title: row.direction === "in" ? `Device request from ${who}` : `Device invite for ${who}`,
68
+ detail: "Device admission actions are not available yet.",
69
+ };
70
+ }
55
71
  if (row.type === "contact") {
56
72
  if (row.direction === "in") {
73
+ if (row.recipientUserId) {
74
+ return {
75
+ title: `Connection request to ${who}`,
76
+ detail: "Waiting for them to confirm.",
77
+ };
78
+ }
57
79
  return { title: `${who} wants to connect`, detail: "Accept to add them as a contact." };
58
80
  }
59
81
  if (row.counterpart) {
@@ -65,13 +87,25 @@ function describeInviteRow(row) {
65
87
  };
66
88
  }
67
89
  if (row.direction === "in") {
90
+ if (row.recipientUserId) {
91
+ if (row.mode === "open") {
92
+ return {
93
+ title: `Joining ${group}`,
94
+ detail: "Completing automatically; no approval is required.",
95
+ };
96
+ }
97
+ return { title: `Request to join ${group}`, detail: `Waiting for ${who} to approve.` };
98
+ }
68
99
  if (row.mode === "direct") {
69
100
  return {
70
101
  title: `${who} invited you to ${group}`,
71
102
  detail: role ? `You would join as ${role}.` : "",
72
103
  };
73
104
  }
74
- return { title: `Joining ${group}`, detail: `Waiting for ${who} to approve.` };
105
+ return {
106
+ title: `${who} wants to join ${group}`,
107
+ detail: role ? `Requested as ${role}. Approve or deny.` : "Approve or deny.",
108
+ };
75
109
  }
76
110
  if (row.mode === "direct") {
77
111
  return { title: `Invited ${who} to ${group}`, detail: "Waiting for them to accept." };
@@ -87,21 +121,45 @@ function describeInviteRow(row) {
87
121
  detail: `${row.mode === "open" ? "Open" : "Approval required"}${role ? ` · ${role}` : ""}`,
88
122
  };
89
123
  }
90
- function actionsFor(row) {
124
+ /**
125
+ * Group an invite by what the signed-in user can do with it.
126
+ *
127
+ * Pending rows that need a decision are `attention`. Pending rows waiting on
128
+ * someone else, including links the user issued, are `waiting`.
129
+ *
130
+ * @param row - Invite row from the personal Invites table.
131
+ */
132
+ function classifyInvite(row) {
91
133
  if (row.status !== "pending") {
134
+ return "history";
135
+ }
136
+ return actionsForInvite(row).some((action) => action !== "revoke") ? "attention" : "waiting";
137
+ }
138
+ /**
139
+ * Return actions that are valid from the local user's perspective.
140
+ *
141
+ * Inbound rows with `recipientUserId` were initiated locally and are waiting
142
+ * for that recipient. Actionable profile requests and join requests omit it.
143
+ */
144
+ function actionsForInvite(row) {
145
+ if (row.status !== "pending" || row.type === "device") {
146
+ return [];
147
+ }
148
+ if (row.direction === "out") {
149
+ return ["revoke"];
150
+ }
151
+ if (row.recipientUserId) {
92
152
  return [];
93
153
  }
94
154
  if (row.direction === "in") {
95
- // Inbound rows I can act on: contact requests and direct group invites.
96
155
  if (row.type === "contact" || row.mode === "direct") {
97
156
  return ["accept", "decline"];
98
157
  }
99
- return []; // my own outstanding join request; nothing to do but wait
100
- }
101
- if (row.counterpart && row.type === "group" && row.mode !== "direct") {
102
- return ["approve", "deny"];
158
+ if (row.type === "group" && row.mode === "approve" && row.counterpart) {
159
+ return ["approve", "deny"];
160
+ }
103
161
  }
104
- return ["revoke"];
162
+ return [];
105
163
  }
106
164
  const ACTION_LABELS = {
107
165
  accept: { text: "Accept", className: "btn-primary" },
@@ -110,6 +168,7 @@ const ACTION_LABELS = {
110
168
  deny: { text: "Deny", className: "btn-outline-secondary" },
111
169
  revoke: { text: "Revoke", className: "btn-outline-danger" },
112
170
  };
171
+ /** One invite row and the actions its direction and status allow. */
113
172
  function InviteRow({ row }) {
114
173
  const [busy, setBusy] = (0, react_1.useState)(undefined);
115
174
  const [error, setError] = (0, react_1.useState)("");
@@ -138,19 +197,5 @@ function InviteRow({ row }) {
138
197
  setBusy(undefined);
139
198
  }
140
199
  };
141
- return ((0, jsx_runtime_1.jsxs)("div", { className: "list-group-item", children: [(0, jsx_runtime_1.jsxs)("div", { className: "d-flex justify-content-between align-items-center gap-2 flex-wrap", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-grow-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "fw-semibold", children: title }), detail ? (0, jsx_runtime_1.jsx)("small", { className: "text-muted d-block", children: detail }) : null, row.deliveryState === "queued" ? ((0, jsx_runtime_1.jsx)("small", { className: "text-warning d-block", children: "Queued until they are reachable" })) : null, row.status !== "pending" ? ((0, jsx_runtime_1.jsx)("small", { className: "text-muted d-block text-capitalize", children: row.status })) : null] }), (0, jsx_runtime_1.jsx)("div", { className: "d-flex gap-1", children: actionsFor(row).map((action) => ((0, jsx_runtime_1.jsx)("button", { type: "button", className: `btn btn-sm ${ACTION_LABELS[action].className}`, disabled: busy !== undefined, onClick: () => void run(action), children: busy === action ? "…" : ACTION_LABELS[action].text }, action))) })] }), error ? (0, jsx_runtime_1.jsx)("div", { className: "alert alert-danger py-1 px-2 small mt-2 mb-0", children: error }) : null] }));
142
- }
143
- /**
144
- * Live list of invite rows with the actions each one supports. Subscribes to the `Invites`
145
- * table directly, so it updates when replies arrive on any of the user's devices.
146
- */
147
- function PendingInvitesList(props) {
148
- const rows = useInviteRows(props);
149
- if (!rows) {
150
- return null;
151
- }
152
- if (rows.length === 0 && props.hideWhenEmpty) {
153
- return null;
154
- }
155
- return ((0, jsx_runtime_1.jsxs)("section", { className: "mb-3", children: [props.title ? (0, jsx_runtime_1.jsx)("h6", { className: "mb-2", children: props.title }) : null, rows.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: "text-muted small mb-0", children: "No pending invites." })) : ((0, jsx_runtime_1.jsx)("div", { className: "list-group", children: rows.map((row) => ((0, jsx_runtime_1.jsx)(InviteRow, { row: row }, row.inviteId))) }))] }));
200
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "list-group-item", children: [(0, jsx_runtime_1.jsxs)("div", { className: "d-flex justify-content-between align-items-center gap-2 flex-wrap", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-grow-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "fw-semibold", children: [(0, jsx_runtime_1.jsx)("span", { className: "badge text-bg-light border me-2 text-capitalize", children: row.type }), title] }), detail ? (0, jsx_runtime_1.jsx)("small", { className: "text-muted d-block", children: detail }) : null, row.deliveryState === "queued" ? ((0, jsx_runtime_1.jsx)("small", { className: "text-warning d-block", children: "Waiting for a route; Peers will retry automatically" })) : null, row.status !== "pending" ? ((0, jsx_runtime_1.jsx)("small", { className: "text-muted d-block text-capitalize", children: row.status })) : null] }), (0, jsx_runtime_1.jsx)("div", { className: "d-flex gap-1", children: actionsForInvite(row).map((action) => ((0, jsx_runtime_1.jsx)("button", { type: "button", className: `btn btn-sm ${ACTION_LABELS[action].className}`, disabled: busy !== undefined, onClick: () => void run(action), children: busy === action ? "…" : ACTION_LABELS[action].text }, action))) })] }), error ? (0, jsx_runtime_1.jsx)("div", { className: "alert alert-danger py-1 px-2 small mt-2 mb-0", children: error }) : null] }));
156
201
  }
@@ -4,70 +4,15 @@ exports.getNetworkDiagnosticsConsumer = getNetworkDiagnosticsConsumer;
4
4
  exports.getNetworkControlConsumer = getNetworkControlConsumer;
5
5
  exports.getNetworkViewerPlatformApi = getNetworkViewerPlatformApi;
6
6
  const peers_sdk_1 = require("@peers-app/peers-sdk");
7
- /** Default wait for the host transport before treating diagnostics as unavailable. */
8
- const HOST_TRANSPORT_TIMEOUT_MS = 10_000;
9
- let cachedConsumers;
10
- let pendingConsumers;
11
- function disposeCachedConsumers() {
12
- cachedConsumers?.diagnostics.dispose();
13
- cachedConsumers?.control.dispose();
14
- cachedConsumers = undefined;
15
- }
16
- (0, peers_sdk_1.subscribeHostContractTransport)((transport) => {
17
- if (cachedConsumers && cachedConsumers.transport !== transport) {
18
- disposeCachedConsumers();
19
- }
20
- }, { emitCurrent: false });
21
- async function loadConsumers(transport) {
22
- disposeCachedConsumers();
23
- const diagnostics = (0, peers_sdk_1.createContractConsumer)((0, peers_sdk_1.getNetworkDiagnosticsContractDefinition)(), transport);
24
- const control = (0, peers_sdk_1.createContractConsumer)((0, peers_sdk_1.getNetworkControlContractDefinition)(), transport);
25
- try {
26
- await diagnostics.loadingPromise;
27
- if ((0, peers_sdk_1.getHostContractTransport)() !== transport) {
28
- diagnostics.dispose();
29
- control.dispose();
30
- // Clear before recursing so getConsumers can start a fresh in-flight memo for the
31
- // current transport, and so this promise's finally does not wipe that newer memo.
32
- pendingConsumers = undefined;
33
- return getConsumers();
34
- }
35
- cachedConsumers = { transport, diagnostics, control };
36
- return cachedConsumers;
37
- }
38
- catch (error) {
39
- diagnostics.dispose();
40
- control.dispose();
41
- throw error;
42
- }
43
- }
44
- async function getConsumers() {
45
- const transport = (0, peers_sdk_1.getHostContractTransport)() ??
46
- (await (0, peers_sdk_1.waitForHostContractTransport)({ timeoutMs: HOST_TRANSPORT_TIMEOUT_MS }));
47
- if (cachedConsumers?.transport === transport) {
48
- return cachedConsumers;
49
- }
50
- if (pendingConsumers) {
51
- return pendingConsumers;
52
- }
53
- const loadPromise = loadConsumers(transport);
54
- pendingConsumers = loadPromise;
55
- try {
56
- return await loadPromise;
57
- }
58
- finally {
59
- if (pendingConsumers === loadPromise) {
60
- pendingConsumers = undefined;
61
- }
62
- }
63
- }
7
+ const diagnostics = (0, peers_sdk_1.hostContractConsumer)((0, peers_sdk_1.getNetworkDiagnosticsContractDefinition)());
8
+ const control = (0, peers_sdk_1.hostContractConsumer)((0, peers_sdk_1.getNetworkControlContractDefinition)());
64
9
  /** Return a typed diagnostics consumer bound to the current local host transport. */
65
10
  async function getNetworkDiagnosticsConsumer() {
66
- return (await getConsumers()).diagnostics;
11
+ return diagnostics.get();
67
12
  }
68
13
  /** Return a typed control consumer bound to the current local host transport. */
69
14
  async function getNetworkControlConsumer() {
70
- return (await getConsumers()).control;
15
+ return control.get();
71
16
  }
72
17
  /** Return the context-isolated desktop-only capability bridge, when available. */
73
18
  function getNetworkViewerPlatformApi() {
@@ -1 +1,2 @@
1
+ /** Search system apps and known entities, then navigate to their canonical routes. */
1
2
  export declare function GlobalSearch(): import("react/jsx-runtime").JSX.Element;
@@ -14,8 +14,9 @@ const searchConfigs = [
14
14
  { config: mention_configs_1.assistantMentionConfig, category: "Assistants", navigationPath: "assistants" },
15
15
  { config: mention_configs_1.workflowMentionConfig, category: "Workflows", navigationPath: "workflows" },
16
16
  { config: mention_configs_1.valueTypeMentionConfig, category: "Types", navigationPath: "peer-types" },
17
- { config: mention_configs_1.userMentionConfig, category: "Users", navigationPath: "contacts" },
17
+ { config: mention_configs_1.userMentionConfig, category: "People", navigationPath: "identity/people" },
18
18
  ];
19
+ /** Search system apps and known entities, then navigate to their canonical routes. */
19
20
  function GlobalSearch() {
20
21
  const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
21
22
  const [packages] = (0, hooks_1.useObservable)(routes_loader_1.allPackages);
@@ -43,7 +43,8 @@ const tooltip_1 = require("../../components/tooltip");
43
43
  const globals = __importStar(require("../../globals"));
44
44
  const hooks_1 = require("../../hooks");
45
45
  const layout_picker_1 = require("../../root-layout/layout-picker");
46
- const device_pairing_1 = require("../device-pairing");
46
+ const identity_ipc_1 = require("../device-pairing/identity-ipc");
47
+ const identity_routes_1 = require("../identity/identity-routes");
47
48
  const color_mode_dropdown_1 = require("./color-mode-dropdown");
48
49
  const isBrowserPwaHost = typeof window !== "undefined" &&
49
50
  !window.electronAPI &&
@@ -53,25 +54,25 @@ function getAppVersion() {
53
54
  }
54
55
  /** Application settings organized by user, system, and developer concerns. */
55
56
  const SettingsPage = () => {
56
- return ((0, jsx_runtime_1.jsx)("div", { className: "container-fluid", children: (0, jsx_runtime_1.jsx)(tabs_1.Tabs, { tabs: [
57
- {
58
- name: "User",
59
- content: (0, jsx_runtime_1.jsx)(UserSettingsTab, {}),
60
- active: true,
61
- },
62
- {
63
- name: "Appearance",
64
- content: (0, jsx_runtime_1.jsx)(AppearanceSettingsTab, {}),
65
- },
66
- {
67
- name: "Advanced",
68
- content: (0, jsx_runtime_1.jsx)(AdvancedSettingsTab, {}),
69
- },
70
- ] }) }));
57
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "d-flex flex-column h-100 overflow-hidden", style: { minHeight: 0 }, children: [(0, jsx_runtime_1.jsx)("div", { className: "container-fluid flex-grow-1 overflow-auto", style: { minHeight: 0 }, children: (0, jsx_runtime_1.jsx)(tabs_1.Tabs, { tabs: [
58
+ {
59
+ name: "User",
60
+ content: (0, jsx_runtime_1.jsx)(UserSettingsTab, {}),
61
+ active: true,
62
+ },
63
+ {
64
+ name: "Appearance",
65
+ content: (0, jsx_runtime_1.jsx)(AppearanceSettingsTab, {}),
66
+ },
67
+ {
68
+ name: "Advanced",
69
+ content: (0, jsx_runtime_1.jsx)(AdvancedSettingsTab, {}),
70
+ },
71
+ ] }) }), (0, jsx_runtime_1.jsxs)("footer", { className: "flex-shrink-0 border-top px-3 py-2 small text-muted", children: ["Peers ", getAppVersion()] })] }));
71
72
  };
72
73
  exports.SettingsPage = SettingsPage;
73
74
  const UserSettingsTab = () => {
74
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ProfileSection, {}), (0, jsx_runtime_1.jsx)(AddDeviceSection, {}), (0, jsx_runtime_1.jsx)(LogoutSection, {})] }));
75
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ProfileSection, {}), (0, jsx_runtime_1.jsx)(IdentityAccountSection, {}), (0, jsx_runtime_1.jsx)(AddDeviceSection, {}), (0, jsx_runtime_1.jsx)(LogoutSection, {})] }));
75
76
  };
76
77
  const AppearanceSettingsTab = () => {
77
78
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("h5", { className: "mb-3", children: "Appearance" }), (0, jsx_runtime_1.jsx)("div", { className: "mb-3", children: (0, jsx_runtime_1.jsx)(color_mode_dropdown_1.ColorModeDropdown, {}) }), (0, jsx_runtime_1.jsx)("div", { className: "mb-3", children: (0, jsx_runtime_1.jsx)(layout_picker_1.LayoutPicker, {}) })] }));
@@ -80,30 +81,10 @@ const AdvancedSettingsTab = () => {
80
81
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("h5", { className: "mb-3", children: "Advanced Settings" }), (0, jsx_runtime_1.jsx)(PackagesRootDirectory, {}), (0, jsx_runtime_1.jsx)(ReloadPackagesOnPageRefresh, {}), (0, jsx_runtime_1.jsx)(AutoUpdatePeersCore, {}), (0, jsx_runtime_1.jsx)(ResetDeviceSyncInfos, {}), (0, jsx_runtime_1.jsx)(DeleteLocalDatabase, {}), (0, jsx_runtime_1.jsx)(CleanupOldDataDir, {}), (0, jsx_runtime_1.jsx)(ImportOldPeersData, {}), (0, jsx_runtime_1.jsx)(ResetChangeTracking, {})] }));
81
82
  };
82
83
  const ProfileSection = () => {
83
- const [deviceId] = (0, hooks_1.useObservable)(peers_sdk_1.thisDeviceId);
84
- const deviceName = (0, hooks_1.useObservableState)("");
85
- const savedDeviceName = (0, hooks_1.useObservableState)("");
86
84
  const me = (0, hooks_1.usePromise)(async () => {
87
85
  const userContext = await (0, peers_sdk_1.getUserContext)();
88
86
  return (0, peers_sdk_1.Users)(userContext.userDataContext).initDoc(globals.me);
89
87
  });
90
- // Load device name
91
- (0, react_1.useEffect)(() => {
92
- const loadDevice = async () => {
93
- if (!deviceId)
94
- return;
95
- try {
96
- const userContext = await (0, peers_sdk_1.getUserContext)();
97
- const device = await (0, peers_sdk_1.Devices)(userContext.userDataContext).get(deviceId);
98
- deviceName((device?.name || "").slice(0, peers_sdk_1.DISPLAY_NAME_MAX_LENGTH));
99
- savedDeviceName(device?.name || "");
100
- }
101
- catch (err) {
102
- console.error("Error loading device name:", err);
103
- }
104
- };
105
- loadDevice();
106
- }, [deviceId, deviceName, savedDeviceName]);
107
88
  const handleSave = async () => {
108
89
  try {
109
90
  // Save user profile (only when it actually changed). Pass me.toJS() — the
@@ -117,21 +98,6 @@ const ProfileSection = () => {
117
98
  me.qs.name(updatedUser.name);
118
99
  me.q(0); // Reset change counter
119
100
  }
120
- // Save device name if changed
121
- if (deviceId && deviceName() !== savedDeviceName()) {
122
- const userContext = await (0, peers_sdk_1.getUserContext)();
123
- const devicesTable = (0, peers_sdk_1.Devices)(userContext.userDataContext);
124
- const device = (await devicesTable.get(deviceId)) || {
125
- deviceId,
126
- userId: userContext.userId,
127
- firstSeen: new Date(),
128
- lastSeen: new Date(),
129
- trustLevel: peers_sdk_1.TrustLevel.NewDevice,
130
- };
131
- device.name = deviceName() || undefined;
132
- await devicesTable.save(device);
133
- savedDeviceName(deviceName());
134
- }
135
101
  }
136
102
  catch (err) {
137
103
  console.error("Error saving profile:", err);
@@ -140,16 +106,17 @@ const ProfileSection = () => {
140
106
  };
141
107
  // Subscribe to changes
142
108
  (0, hooks_1.useObservable)(me?.q);
143
- (0, hooks_1.useObservable)(deviceName);
144
109
  if (!me) {
145
110
  return null;
146
111
  }
147
- const hasChanges = !!me.q() || deviceName() !== savedDeviceName();
148
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center mb-3", children: [(0, jsx_runtime_1.jsx)("h5", { className: "mb-0 me-auto", children: "Settings" }), (0, jsx_runtime_1.jsx)("button", { className: "btn btn-primary btn-sm", onClick: handleSave, disabled: !hasChanges, children: "Save" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsx)("small", { className: "form-label", children: "Display Name:" }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: me.qs.name, className: "form-control", maxLength: peers_sdk_1.DISPLAY_NAME_MAX_LENGTH, placeholder: "Enter your name" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { className: "form-label", children: ["Device Name:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "Give this device a friendly name to identify it in your network." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: deviceName, className: "form-control", maxLength: peers_sdk_1.DISPLAY_NAME_MAX_LENGTH, placeholder: "e.g., My Laptop" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { className: "form-label", children: ["User ID:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "This uniquely identifies you to all other users." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: me.userId, className: "form-control", disabled: true })] }), (0, jsx_runtime_1.jsxs)("div", { className: "row", children: [(0, jsx_runtime_1.jsxs)("div", { className: "col-md-6 mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { className: "form-label", children: ["Public Key:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "This is your public key that other users will use to verify your signatures." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: me.publicKey, className: "form-control form-control-sm", disabled: true })] }), (0, jsx_runtime_1.jsxs)("div", { className: "col-md-6 mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { className: "form-label", children: ["Public Box Key:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "This is the public key that other users can use to encrypt data so that only you can open it." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: me.publicBoxKey, className: "form-control form-control-sm", disabled: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { className: "form-label", children: ["Device ID:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "This uniquely identifies this device on Peers networks." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: deviceId || "", className: "form-control form-control-sm", disabled: true })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsx)("small", { className: "form-label", children: "App Version:" }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: getAppVersion(), className: "form-control form-control-sm", disabled: true })] })] }));
112
+ const hasChanges = !!me.q();
113
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center mb-3", children: [(0, jsx_runtime_1.jsx)("h5", { className: "mb-0 me-auto", children: "Profile" }), (0, jsx_runtime_1.jsx)("button", { className: "btn btn-primary btn-sm", onClick: handleSave, disabled: !hasChanges, children: "Save" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsx)("label", { className: "form-label small", htmlFor: "settings-display-name", children: "Display name" }), (0, jsx_runtime_1.jsx)(input_1.Input, { id: "settings-display-name", value: me.qs.name, className: "form-control", maxLength: peers_sdk_1.DISPLAY_NAME_MAX_LENGTH, placeholder: "Enter your name" })] })] }));
114
+ };
115
+ const IdentityAccountSection = () => {
116
+ return ((0, jsx_runtime_1.jsxs)("section", { className: "mt-4 pt-3 border-top", children: [(0, jsx_runtime_1.jsx)("h6", { children: "Identity account" }), (0, jsx_runtime_1.jsx)("p", { className: "small text-muted", children: "View account identifiers, security keys, this device\u2019s ID, and Peers Services registration." }), (0, jsx_runtime_1.jsx)("a", { href: `#${identity_routes_1.IDENTITY_ACCOUNT_PATH}`, className: "btn btn-outline-primary", children: "View Identity account" })] }));
149
117
  };
150
118
  const AddDeviceSection = () => {
151
- const [open, setOpen] = (0, react_1.useState)(false);
152
- return ((0, jsx_runtime_1.jsxs)("section", { className: "mt-4 pt-3 border-top", children: [(0, jsx_runtime_1.jsx)("h6", { children: "Add another device" }), (0, jsx_runtime_1.jsx)("p", { className: "small text-muted", children: "On the new device choose \u201CSign in from another device\u201D, then type the code it shows here and approve. Account access is transferred only after you approve." }), open ? ((0, jsx_runtime_1.jsx)(device_pairing_1.SourceDevicePairing, { onClose: () => setOpen(false) })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", className: "btn btn-outline-primary", onClick: () => setOpen(true), children: "Add another device" }))] }));
119
+ return ((0, jsx_runtime_1.jsxs)("section", { className: "mt-4 pt-3 border-top", children: [(0, jsx_runtime_1.jsx)("h6", { children: "Add another device" }), (0, jsx_runtime_1.jsx)("p", { className: "small text-muted", children: "On the new device choose \u201CSign in from another device\u201D, then type the code it shows on Identity \u2192 Devices and approve. Account access is transferred only after you approve." }), (0, jsx_runtime_1.jsx)("a", { href: `#${identity_routes_1.IDENTITY_PAIR_PATH}`, className: "btn btn-outline-primary", children: "Add another device" })] }));
153
120
  };
154
121
  const PackagesRootDirectory = () => {
155
122
  return ((0, jsx_runtime_1.jsxs)("div", { className: "mt-3", children: [(0, jsx_runtime_1.jsxs)("small", { children: ["Packages Directory:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: `Changing this will not effect existing packages.` })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: peers_sdk_1.packagesRootDir, className: "form-control" })] }));
@@ -317,6 +284,6 @@ const LogoutSection = () => {
317
284
  "Make sure you have your User ID and Secret Key saved securely, or you will lose access to your account.");
318
285
  if (!confirmed)
319
286
  return;
320
- await peers_sdk_1.rpcServerCalls.logout();
287
+ await (await (0, identity_ipc_1.identityTools)()).signOut();
321
288
  }, children: "Logout" }) }));
322
289
  };
@@ -6,6 +6,7 @@ const peers_sdk_1 = require("@peers-app/peers-sdk");
6
6
  const react_1 = require("react");
7
7
  const hooks_1 = require("../hooks");
8
8
  const device_pairing_1 = require("./device-pairing");
9
+ const identity_ipc_1 = require("./device-pairing/identity-ipc");
9
10
  const color_mode_dropdown_1 = require("./settings/color-mode-dropdown");
10
11
  const SetupUser = () => {
11
12
  const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
@@ -25,9 +26,9 @@ const SetupUser = () => {
25
26
  // Generate new user credentials
26
27
  const keys = (0, peers_sdk_1.newKeys)();
27
28
  const _userId = (0, peers_sdk_1.newid)();
28
- // Call setUserIdAndSecretKey. This triggers device init, which installs
29
- // peers-core into the personal context (S3-first, bundle fallback).
30
- await peers_sdk_1.rpcServerCalls.setUserIdAndSecretKey(_userId, keys.secretKey);
29
+ // signIn triggers device init, which installs peers-core into the personal
30
+ // context (S3-first, bundle fallback).
31
+ await (await (0, identity_ipc_1.identityTools)()).signIn({ userId: _userId, secretKey: keys.secretKey });
31
32
  // Success - reload the app (peers-services registration runs after Welcome modal)
32
33
  window.location.reload();
33
34
  }
@@ -57,8 +58,7 @@ const SetupUser = () => {
57
58
  if (msg !== msgOpened) {
58
59
  throw new Error("Secret key validation failed");
59
60
  }
60
- // Call setUserIdAndSecretKey
61
- await peers_sdk_1.rpcServerCalls.setUserIdAndSecretKey(userId, keys.secretKey);
61
+ await (await (0, identity_ipc_1.identityTools)()).signIn({ userId, secretKey: keys.secretKey });
62
62
  // Success - reload the app
63
63
  window.location.reload();
64
64
  }
@@ -1,5 +1,7 @@
1
1
  import { type IToolAccessControlConsumer } from "@peers-app/peers-sdk";
2
2
  /**
3
3
  * Return a typed local-host consumer for Tool Access Control in `dataContextId`.
4
+ *
5
+ * One consumer is cached per data context and rebuilt when the host transport changes.
4
6
  */
5
7
  export declare function getToolAccessControlConsumer(dataContextId: string): Promise<IToolAccessControlConsumer>;