@peers-app/peers-ui 0.0.16 → 0.6.14
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/.claude/settings.local.json +34 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/screens/groups/group-members.js +1 -1
- package/dist/screens/setup-user.d.ts +1 -1
- package/dist/screens/setup-user.js +122 -219
- package/dist/screens/variables/variable-list.js +1 -1
- package/dist/tabs-layout/tabs-layout.d.ts +4 -0
- package/dist/tabs-layout/tabs-layout.js +24 -3
- package/dist/ui-router/routes-loader.d.ts +0 -1
- package/dist/ui-router/routes-loader.js +30 -32
- package/dist/ui-router/ui-loader.js +17 -15
- package/package.json +8 -8
- package/src/index.tsx +0 -4
- package/src/screens/groups/group-members.tsx +1 -1
- package/src/screens/setup-user.tsx +224 -329
- package/src/screens/variables/variable-list.tsx +1 -1
- package/src/tabs-layout/tabs-layout.tsx +28 -5
- package/src/ui-router/routes-loader.ts +31 -30
- package/src/ui-router/ui-loader.tsx +20 -18
- package/dist/app.d.ts +0 -9
- package/dist/app.js +0 -54
- package/dist/layout-vars.d.ts +0 -6
- package/dist/layout-vars.js +0 -10
- package/dist/three-bar-layout/left-bar-content.d.ts +0 -7
- package/dist/three-bar-layout/left-bar-content.js +0 -151
- package/dist/three-bar-layout/right-bar-content.d.ts +0 -2
- package/dist/three-bar-layout/right-bar-content.js +0 -64
- package/dist/three-bar-layout/three-bar-layout.d.ts +0 -5
- package/dist/three-bar-layout/three-bar-layout.js +0 -218
- package/src/app.tsx +0 -59
- package/src/layout-vars.ts +0 -8
- package/src/three-bar-layout/left-bar-content.tsx +0 -202
- package/src/three-bar-layout/right-bar-content.tsx +0 -67
- package/src/three-bar-layout/three-bar-layout.tsx +0 -297
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(mkdir:*)",
|
|
5
|
+
"Bash(yarn add:*)",
|
|
6
|
+
"Bash(yarn test:*)",
|
|
7
|
+
"Bash(npm test)",
|
|
8
|
+
"Bash(yarn build)",
|
|
9
|
+
"Bash(yarn jest:*)",
|
|
10
|
+
"Bash(mv:*)",
|
|
11
|
+
"Bash(npm run build:*)",
|
|
12
|
+
"Bash(cd:*)",
|
|
13
|
+
"Bash(npm test:*)",
|
|
14
|
+
"Bash(npm run test:*)",
|
|
15
|
+
"Bash(yarn tsc:*)",
|
|
16
|
+
"WebFetch(domain:developer.mozilla.org)",
|
|
17
|
+
"Read(/Users/mark.archer/peers-device/src/**)",
|
|
18
|
+
"Read(/Users/mark.archer/peers-packages/tasks/**)",
|
|
19
|
+
"Read(/Users/mark.archer/peers-packages/tasks/**)",
|
|
20
|
+
"Read(/Users/mark.archer/peers-packages/tasks/**)",
|
|
21
|
+
"Read(/Users/mark.archer/peers-packages/tasks/**)",
|
|
22
|
+
"Read(/Users/mark.archer/peers-packages/tasks/src/**)",
|
|
23
|
+
"Read(/Users/mark.archer/peers-packages/tasks/dist/**)",
|
|
24
|
+
"Read(/Users/mark.archer/peers-packages/tasks/dist/**)",
|
|
25
|
+
"Read(/Users/mark.archer/peers-packages/tasks/dist/**)",
|
|
26
|
+
"Read(/Users/mark.archer/peers-packages/tasks/src/**)",
|
|
27
|
+
"Read(/Users/mark.archer/peers-packages/tasks/src/**)"
|
|
28
|
+
],
|
|
29
|
+
"deny": [],
|
|
30
|
+
"additionalDirectories": [
|
|
31
|
+
"/Users/mark.archer/peers-packages/tasks/dist"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,7 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./app"), exports);
|
|
18
|
-
__exportStar(require("./three-bar-layout/three-bar-layout"), exports);
|
|
19
17
|
__exportStar(require("./screens/events/cron"), exports);
|
|
20
18
|
__exportStar(require("./tabs-layout/tabs-layout"), exports);
|
|
@@ -54,7 +54,7 @@ const GroupMembersUI = (props) => {
|
|
|
54
54
|
// Check if current user has admin privileges in this group
|
|
55
55
|
const userPermissions = (0, hooks_1.usePromise)(async () => {
|
|
56
56
|
const currentUserContext = await (0, peers_sdk_1.getUserContext)();
|
|
57
|
-
const currentUserId = currentUserContext.userId
|
|
57
|
+
const currentUserId = currentUserContext.userId;
|
|
58
58
|
const userRole = await (0, peers_sdk_1.getUserRole)(groupId, currentUserId);
|
|
59
59
|
return {
|
|
60
60
|
isMember: !!userRole,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const SetupUser: () => React.JSX.Element;
|
|
2
|
+
export declare const SetupUser: () => React.JSX.Element | null;
|
|
@@ -36,235 +36,138 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.SetupUser = void 0;
|
|
37
37
|
const peers_sdk_1 = require("@peers-app/peers-sdk");
|
|
38
38
|
const react_1 = __importStar(require("react"));
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const tooltip_1 = require("../components/tooltip");
|
|
42
|
-
const globals_1 = require("../globals");
|
|
43
|
-
async function sendNewUserMessage(userId) {
|
|
44
|
-
const user = await (0, peers_sdk_1.Users)().get(userId);
|
|
45
|
-
if (!user) {
|
|
46
|
-
throw new Error('user not found');
|
|
47
|
-
}
|
|
48
|
-
const primaryAssistant = await (0, peers_sdk_1.getPrimaryAssistant)();
|
|
49
|
-
const message = {
|
|
50
|
-
messageId: (0, peers_sdk_1.newid)(),
|
|
51
|
-
message: [
|
|
52
|
-
`Hi, ${user.name}! Welcome to Peers! I'm your primary AI assistant.`,
|
|
53
|
-
"\n\n",
|
|
54
|
-
"If you have any questions, just ask! I'm here to help.",
|
|
55
|
-
// `\nRemind Mark to add some Getting-Started tasks that I can work through with you.`,
|
|
56
|
-
].join(' '),
|
|
57
|
-
userId: user.userId,
|
|
58
|
-
assistantId: primaryAssistant?.assistantId,
|
|
59
|
-
channelId: user.userId,
|
|
60
|
-
createdAt: new Date(),
|
|
61
|
-
};
|
|
62
|
-
await (0, peers_sdk_1.Messages)().insert(message);
|
|
63
|
-
(0, globals_1.openThread)(message.messageId);
|
|
64
|
-
}
|
|
39
|
+
const hooks_1 = require("../hooks");
|
|
40
|
+
const color_mode_dropdown_1 = require("./settings/color-mode-dropdown");
|
|
65
41
|
const SetupUser = () => {
|
|
66
|
-
const [
|
|
67
|
-
|
|
42
|
+
const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
|
|
43
|
+
const [step, setStep] = (0, react_1.useState)('select-user-type');
|
|
44
|
+
const [isExistingUser, setIsExistingUser] = (0, react_1.useState)(null);
|
|
45
|
+
const [userId, setUserId] = (0, react_1.useState)('');
|
|
68
46
|
const [secretKey, setSecretKey] = (0, react_1.useState)('');
|
|
69
|
-
const [
|
|
70
|
-
const [
|
|
71
|
-
const
|
|
72
|
-
async
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
keys = (0, peers_sdk_1.loadKeys)(secretKey);
|
|
86
|
-
const msg = (0, peers_sdk_1.newid)();
|
|
87
|
-
const msgSigned = (0, peers_sdk_1.signMessageWithSecretKey)(msg, keys.secretKey);
|
|
88
|
-
const msgOpened = (0, peers_sdk_1.openMessageWithPublicKey)(msgSigned, keys.publicKey);
|
|
89
|
-
if (msg !== msgOpened) {
|
|
90
|
-
throw new Error('signed message does not match');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch (e) {
|
|
94
|
-
confirm('Invalid secret key');
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
keys = (0, peers_sdk_1.newKeys)();
|
|
47
|
+
const [error, setError] = (0, react_1.useState)('');
|
|
48
|
+
const [isValidating, setIsValidating] = (0, react_1.useState)(false);
|
|
49
|
+
const isDark = _colorMode === 'dark';
|
|
50
|
+
const handleNewUser = async () => {
|
|
51
|
+
setError('');
|
|
52
|
+
setIsValidating(true);
|
|
53
|
+
try {
|
|
54
|
+
// Generate new user credentials
|
|
55
|
+
const keys = (0, peers_sdk_1.newKeys)();
|
|
56
|
+
const _userId = (0, peers_sdk_1.newid)();
|
|
57
|
+
// Call setUserIdAndSecretKey
|
|
58
|
+
await peers_sdk_1.rpcServerCalls.setUserIdAndSecretKey(_userId, keys.secretKey);
|
|
59
|
+
// Success - reload the app
|
|
60
|
+
window.location.reload();
|
|
100
61
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (!_me) {
|
|
105
|
-
_me = {
|
|
106
|
-
userId: _userId,
|
|
107
|
-
name,
|
|
108
|
-
publicKey: keys.publicKey,
|
|
109
|
-
publicBoxKey: keys.publicBoxKey,
|
|
110
|
-
};
|
|
111
|
-
await (0, peers_sdk_1.Users)().insert(_me);
|
|
62
|
+
catch (err) {
|
|
63
|
+
setError('Error creating new user: ' + String(err).replaceAll('\n', ' '));
|
|
64
|
+
setIsValidating(false);
|
|
112
65
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
66
|
+
};
|
|
67
|
+
const handleExistingUser = async () => {
|
|
68
|
+
setError('');
|
|
69
|
+
// Validate inputs
|
|
70
|
+
if (!userId.trim() || !secretKey.trim()) {
|
|
71
|
+
setError('Please enter both User ID and Secret Key');
|
|
72
|
+
return;
|
|
118
73
|
}
|
|
119
|
-
(0, peers_sdk_1.
|
|
120
|
-
|
|
121
|
-
confirm('Error setting user id and secret key: ' + String(err).replaceAll('\n', ' '));
|
|
122
|
-
return err;
|
|
123
|
-
});
|
|
124
|
-
if (result) {
|
|
74
|
+
if ((0, peers_sdk_1.isid)(userId) !== true) {
|
|
75
|
+
setError('Invalid User ID format');
|
|
125
76
|
return;
|
|
126
77
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
(0,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
78
|
+
setIsValidating(true);
|
|
79
|
+
try {
|
|
80
|
+
// Validate secret key
|
|
81
|
+
const keys = (0, peers_sdk_1.loadKeys)(secretKey);
|
|
82
|
+
const msg = (0, peers_sdk_1.newid)();
|
|
83
|
+
const msgSigned = (0, peers_sdk_1.signMessageWithSecretKey)(msg, keys.secretKey);
|
|
84
|
+
const msgOpened = (0, peers_sdk_1.openMessageWithPublicKey)(msgSigned, keys.publicKey);
|
|
85
|
+
if (msg !== msgOpened) {
|
|
86
|
+
throw new Error('Secret key validation failed');
|
|
87
|
+
}
|
|
88
|
+
// Call setUserIdAndSecretKey
|
|
89
|
+
await peers_sdk_1.rpcServerCalls.setUserIdAndSecretKey(userId, keys.secretKey);
|
|
90
|
+
// Success - reload the app
|
|
91
|
+
window.location.reload();
|
|
135
92
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
setShowUserKeys(true);
|
|
93
|
+
catch (err) {
|
|
94
|
+
setError('Invalid credentials: ' + String(err).replaceAll('\n', ' '));
|
|
95
|
+
setIsValidating(false);
|
|
140
96
|
}
|
|
97
|
+
};
|
|
98
|
+
// Step 1: Select User Type
|
|
99
|
+
if (step === 'select-user-type' && isExistingUser === null) {
|
|
100
|
+
return (react_1.default.createElement("div", { className: "container-fluid d-flex align-items-start justify-content-center", style: { minHeight: '100vh', paddingTop: '80px', backgroundColor: isDark ? '#212529' : '#f8f9fa' } },
|
|
101
|
+
react_1.default.createElement("div", { className: "card shadow", style: { maxWidth: '500px', width: '100%', backgroundColor: isDark ? '#2d3238' : '#ffffff' } },
|
|
102
|
+
react_1.default.createElement("div", { className: "card-body p-4 p-md-5" },
|
|
103
|
+
react_1.default.createElement("div", { className: "text-center mb-4" },
|
|
104
|
+
react_1.default.createElement("h2", { className: `fw-bold mb-2 ${isDark ? 'text-light' : ''}` }, "Welcome to Peers"),
|
|
105
|
+
react_1.default.createElement("p", { className: isDark ? 'text-light opacity-75' : 'text-muted' }, "Let's get you set up")),
|
|
106
|
+
react_1.default.createElement("div", { className: "d-grid gap-3" },
|
|
107
|
+
react_1.default.createElement("button", { className: "btn btn-lg btn-primary py-3", onClick: () => setIsExistingUser(false) },
|
|
108
|
+
react_1.default.createElement("div", { className: "d-flex align-items-center justify-content-center" },
|
|
109
|
+
react_1.default.createElement("i", { className: "bi bi-person-plus fs-4 me-2" }),
|
|
110
|
+
react_1.default.createElement("div", { className: "text-start" },
|
|
111
|
+
react_1.default.createElement("div", { className: "fw-semibold" }, "I'm a New User"),
|
|
112
|
+
react_1.default.createElement("small", { className: "opacity-75" }, "Create a new account")))),
|
|
113
|
+
react_1.default.createElement("button", { className: `btn btn-lg py-3 ${isDark ? 'btn-outline-light' : 'btn-outline-primary'}`, onClick: () => setIsExistingUser(true) },
|
|
114
|
+
react_1.default.createElement("div", { className: "d-flex align-items-center justify-content-center" },
|
|
115
|
+
react_1.default.createElement("i", { className: "bi bi-box-arrow-in-right fs-4 me-2" }),
|
|
116
|
+
react_1.default.createElement("div", { className: "text-start" },
|
|
117
|
+
react_1.default.createElement("div", { className: "fw-semibold" }, "I'm an Existing User"),
|
|
118
|
+
react_1.default.createElement("small", { className: "opacity-75" }, "Sign in with your credentials")))))))));
|
|
141
119
|
}
|
|
142
|
-
|
|
143
|
-
|
|
120
|
+
// Step 2: New User Confirmation
|
|
121
|
+
if (isExistingUser === false) {
|
|
122
|
+
return (react_1.default.createElement("div", { className: "container-fluid d-flex align-items-start justify-content-center", style: { minHeight: '100vh', paddingTop: '80px', backgroundColor: isDark ? '#212529' : '#f8f9fa' } },
|
|
123
|
+
react_1.default.createElement("div", { className: "card shadow", style: { maxWidth: '500px', width: '100%', backgroundColor: isDark ? '#2d3238' : '#ffffff' } },
|
|
124
|
+
react_1.default.createElement("div", { className: "card-body p-4 p-md-5" },
|
|
125
|
+
react_1.default.createElement("div", { className: "text-center mb-4" },
|
|
126
|
+
react_1.default.createElement("i", { className: "bi bi-person-plus-fill text-primary fs-1 mb-3 d-block" }),
|
|
127
|
+
react_1.default.createElement("h3", { className: `fw-bold mb-2 ${isDark ? 'text-light' : ''}` }, "Create New Account"),
|
|
128
|
+
react_1.default.createElement("p", { className: isDark ? 'text-light opacity-75' : 'text-muted' }, "We'll generate secure credentials for you")),
|
|
129
|
+
error && (react_1.default.createElement("div", { className: "alert alert-danger", role: "alert" },
|
|
130
|
+
react_1.default.createElement("i", { className: "bi bi-exclamation-triangle me-2" }),
|
|
131
|
+
error)),
|
|
132
|
+
react_1.default.createElement("div", { className: "d-grid gap-2" },
|
|
133
|
+
react_1.default.createElement("button", { className: "btn btn-lg btn-primary", onClick: handleNewUser, disabled: isValidating }, isValidating ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
134
|
+
react_1.default.createElement("span", { className: "spinner-border spinner-border-sm me-2" }),
|
|
135
|
+
"Creating Account...")) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
136
|
+
react_1.default.createElement("i", { className: "bi bi-check-circle me-2" }),
|
|
137
|
+
"Create Account"))),
|
|
138
|
+
react_1.default.createElement("button", { className: "btn btn-outline-secondary", onClick: () => setIsExistingUser(null), disabled: isValidating },
|
|
139
|
+
react_1.default.createElement("i", { className: "bi bi-arrow-left me-2" }),
|
|
140
|
+
"Back"))))));
|
|
144
141
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} },
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
existingUser && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
174
|
-
react_1.default.createElement("br", null),
|
|
175
|
-
react_1.default.createElement("label", null, "User Id"),
|
|
176
|
-
react_1.default.createElement(tooltip_1.Tooltip, { positions: ['top', 'bottom', 'right', 'left'], markdownContent: "The user id that was generated when you first setup your account." }),
|
|
177
|
-
react_1.default.createElement("input", { id: "user-id", type: "text", className: 'form-control', value: userId, onChange: (e) => setUserId(e.target.value), disabled: !existingUser }),
|
|
178
|
-
react_1.default.createElement("br", null),
|
|
179
|
-
react_1.default.createElement("label", null, "Secret Key"),
|
|
180
|
-
react_1.default.createElement(tooltip_1.Tooltip, { positions: ['top', 'bottom', 'right', 'left'], markdownContent: "The secret key for the public key that is currently associated with this account." }),
|
|
181
|
-
react_1.default.createElement("input", { id: "secret-key", type: 'password', className: 'form-control', value: secretKey, disabled: !existingUser, onChange: (e) => setSecretKey(e.target.value) }))),
|
|
182
|
-
react_1.default.createElement("div", { className: "mt-2" },
|
|
183
|
-
react_1.default.createElement("label", null, "Sync with Peers"),
|
|
184
|
-
react_1.default.createElement(tooltip_1.Tooltip, { positions: ['top', 'bottom', 'right', 'left'], markdownContent: [
|
|
185
|
-
"### PLEASE READ",
|
|
186
|
-
'\n',
|
|
187
|
-
"Leave this checked to register your `userId` and `publicKey` with [https://peers.app](https://peers.app) server.",
|
|
188
|
-
"\n\n**No other data is sent to the server.**\n\n",
|
|
189
|
-
"This is not required to use Peers but it is required to use the built-in network services.",
|
|
190
|
-
"Additionally this will ensure that your `userId` is not used publicly by someone else.",
|
|
191
|
-
"\n\n",
|
|
192
|
-
"**This is _highly_ recommended** but if your goal is absolute privacy, uncheck this.",
|
|
193
|
-
"\n\n",
|
|
194
|
-
"If you choose to not do this now, you can still do it later from the settings screen.",
|
|
195
|
-
].join(' ') }),
|
|
196
|
-
"\u00A0",
|
|
197
|
-
react_1.default.createElement("input", { type: "checkbox", checked: registerAccount, onChange: (e) => setRegisterAccount(e.target.checked) })),
|
|
198
|
-
react_1.default.createElement("button", { className: 'btn btn-primary float-end', onClick: e => onSubmit(e) }, "Submit"))))));
|
|
199
|
-
};
|
|
200
|
-
exports.SetupUser = SetupUser;
|
|
201
|
-
const ShowUserKeys = (props) => {
|
|
202
|
-
const { userId, secretKey } = props;
|
|
203
|
-
const [secretKeySaved, setSecretKeySaved] = (0, react_1.useState)(false);
|
|
204
|
-
async function continueToApp() {
|
|
205
|
-
await sendNewUserMessage(userId);
|
|
206
|
-
window.location.reload();
|
|
142
|
+
// Step 3: Existing User Sign In
|
|
143
|
+
if (isExistingUser === true) {
|
|
144
|
+
return (react_1.default.createElement("div", { className: "container-fluid d-flex align-items-start justify-content-center", style: { minHeight: '100vh', paddingTop: '80px', backgroundColor: isDark ? '#212529' : '#f8f9fa' } },
|
|
145
|
+
react_1.default.createElement("div", { className: "card shadow", style: { maxWidth: '500px', width: '100%', backgroundColor: isDark ? '#2d3238' : '#ffffff' } },
|
|
146
|
+
react_1.default.createElement("div", { className: "card-body p-4 p-md-5" },
|
|
147
|
+
react_1.default.createElement("div", { className: "text-center mb-4" },
|
|
148
|
+
react_1.default.createElement("i", { className: "bi bi-box-arrow-in-right text-primary fs-1 mb-3 d-block" }),
|
|
149
|
+
react_1.default.createElement("h3", { className: `fw-bold mb-2 ${isDark ? 'text-light' : ''}` }, "Sign In"),
|
|
150
|
+
react_1.default.createElement("p", { className: isDark ? 'text-light opacity-75' : 'text-muted' }, "Enter your existing credentials")),
|
|
151
|
+
error && (react_1.default.createElement("div", { className: "alert alert-danger", role: "alert" },
|
|
152
|
+
react_1.default.createElement("i", { className: "bi bi-exclamation-triangle me-2" }),
|
|
153
|
+
error)),
|
|
154
|
+
react_1.default.createElement("form", { onSubmit: (e) => { e.preventDefault(); handleExistingUser(); } },
|
|
155
|
+
react_1.default.createElement("div", { className: "mb-3" },
|
|
156
|
+
react_1.default.createElement("label", { htmlFor: "userId", className: "form-label fw-semibold" }, "User ID"),
|
|
157
|
+
react_1.default.createElement("input", { id: "userId", type: "text", className: "form-control form-control-lg", placeholder: "Enter your user ID", value: userId, onChange: (e) => setUserId(e.target.value), disabled: isValidating, autoFocus: true })),
|
|
158
|
+
react_1.default.createElement("div", { className: "mb-4" },
|
|
159
|
+
react_1.default.createElement("label", { htmlFor: "secretKey", className: "form-label fw-semibold" }, "Secret Key"),
|
|
160
|
+
react_1.default.createElement("input", { id: "secretKey", type: "password", className: "form-control form-control-lg", placeholder: "Enter your secret key", value: secretKey, onChange: (e) => setSecretKey(e.target.value), disabled: isValidating })),
|
|
161
|
+
react_1.default.createElement("div", { className: "d-grid gap-2" },
|
|
162
|
+
react_1.default.createElement("button", { type: "submit", className: "btn btn-lg btn-primary", disabled: isValidating }, isValidating ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
163
|
+
react_1.default.createElement("span", { className: "spinner-border spinner-border-sm me-2" }),
|
|
164
|
+
"Signing In...")) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
165
|
+
react_1.default.createElement("i", { className: "bi bi-check-circle me-2" }),
|
|
166
|
+
"Sign In"))),
|
|
167
|
+
react_1.default.createElement("button", { type: "button", className: "btn btn-outline-secondary", onClick: () => setIsExistingUser(null), disabled: isValidating },
|
|
168
|
+
react_1.default.createElement("i", { className: "bi bi-arrow-left me-2" }),
|
|
169
|
+
"Back")))))));
|
|
207
170
|
}
|
|
208
|
-
|
|
209
|
-
"**`NEVER SHARE THIS KEY WITH ANYONE!`**",
|
|
210
|
-
"\n\n",
|
|
211
|
-
"If this key is compromised another user can permanently take over your account.",
|
|
212
|
-
"\n\n",
|
|
213
|
-
"This key is used to:",
|
|
214
|
-
"\n - Sign messages so that other users can verify they were sent from you.",
|
|
215
|
-
"\n - Decrypt boxed data that was encrypted with your public box key.",
|
|
216
|
-
"\n - This allows other users to send data to you securely through public channels.",
|
|
217
|
-
"\n - Encrypt your own private data so that only you can decrypt it.",
|
|
218
|
-
"\n\n",
|
|
219
|
-
"Unlike a password, this key is never sent to the server and is entirely in your control.",
|
|
220
|
-
"This is the foundation of your account's security.",
|
|
221
|
-
"If you lose this key you will lose access to your account.",
|
|
222
|
-
"If this key is compromised your account will be too and you will be putting any groups you are a part of at risk.",
|
|
223
|
-
"\n\n",
|
|
224
|
-
"Since the secret key is never sent to the server, if you lose it you'll lose access to your account.",
|
|
225
|
-
"It is highly recommend to store these in a password manager like [1Password](https://1password.com).",
|
|
226
|
-
].join(' ');
|
|
227
|
-
return (react_1.default.createElement("div", { className: 'container-fluid' },
|
|
228
|
-
react_1.default.createElement("div", { className: "position-relative", style: {
|
|
229
|
-
height: '100vh',
|
|
230
|
-
} },
|
|
231
|
-
react_1.default.createElement("div", { className: "position-absolute top-50 start-50 translate-middle bg-body-tertiary", style: {
|
|
232
|
-
width: '600px',
|
|
233
|
-
padding: '20px',
|
|
234
|
-
border: '1px solid #ccc',
|
|
235
|
-
borderRadius: '5px',
|
|
236
|
-
} },
|
|
237
|
-
react_1.default.createElement("h3", { className: 'text-center' }, "User Created!"),
|
|
238
|
-
react_1.default.createElement("small", null, "User Id:"),
|
|
239
|
-
react_1.default.createElement(tooltip_1.Tooltip, { markdownContent: "This uniquely identifies you to all other users." }),
|
|
240
|
-
react_1.default.createElement("button", { className: 'btn btn-secondary-outline', onClick: () => {
|
|
241
|
-
navigator.clipboard.writeText(userId);
|
|
242
|
-
}, title: "Copy User Id to Clipboard" },
|
|
243
|
-
react_1.default.createElement("i", { className: "bi bi-copy" })),
|
|
244
|
-
react_1.default.createElement(input_1.Input, { value: globals_1.me.userId, className: "form-control mb-3", disabled: true }),
|
|
245
|
-
react_1.default.createElement("small", null, "Secret Key:"),
|
|
246
|
-
react_1.default.createElement(tooltip_1.Tooltip, { markdownContent: secretKeyExplainer }),
|
|
247
|
-
react_1.default.createElement("button", { className: 'btn btn-secondary-outline', onClick: () => {
|
|
248
|
-
navigator.clipboard.writeText(props.secretKey);
|
|
249
|
-
}, title: "Copy Secret Key to Clipboard" },
|
|
250
|
-
react_1.default.createElement("i", { className: "bi bi-copy" })),
|
|
251
|
-
react_1.default.createElement("pre", null, secretKey),
|
|
252
|
-
react_1.default.createElement("small", null,
|
|
253
|
-
react_1.default.createElement(markdown_with_mentions_1.MarkdownWithMentions, { content: [
|
|
254
|
-
"**`IMPORTANT:`**",
|
|
255
|
-
"**Copy your User Id and Secret Key to a secure location.**",
|
|
256
|
-
"\n\n",
|
|
257
|
-
"You won't be able to view this key again after you continue.",
|
|
258
|
-
"\n\n",
|
|
259
|
-
"It is highly recommended to store these in a password manager like [1Password](https://1password.com).",
|
|
260
|
-
"\n\n",
|
|
261
|
-
"Unlike a password, this key is never sent to the server and is entirely in your control.",
|
|
262
|
-
"If you lose this key you will lose access to your account and data.",
|
|
263
|
-
].join(' ') })),
|
|
264
|
-
react_1.default.createElement("div", null,
|
|
265
|
-
react_1.default.createElement("label", { style: { textDecoration: 'underline' } }, "I Have Saved My Secret Key"),
|
|
266
|
-
" \u00A0",
|
|
267
|
-
react_1.default.createElement("input", { type: "checkbox", checked: secretKeySaved, onChange: (e) => setSecretKeySaved(e.target.checked) }),
|
|
268
|
-
"\u00A0 \u00A0",
|
|
269
|
-
react_1.default.createElement("button", { disabled: !secretKeySaved, className: (secretKeySaved ? 'btn btn-primary' : 'btn btn-secondary') + ' float-end', onClick: continueToApp }, "Continue"))))));
|
|
171
|
+
return null;
|
|
270
172
|
};
|
|
173
|
+
exports.SetupUser = SetupUser;
|
|
@@ -13,7 +13,7 @@ const ui_loader_1 = require("../../ui-router/ui-loader");
|
|
|
13
13
|
function VariableList() {
|
|
14
14
|
async function newRecord(name) {
|
|
15
15
|
const userContext = await (0, peers_sdk_1.getUserContext)();
|
|
16
|
-
const isPersonal = userContext.currentlyActiveGroupId() === userContext.userId
|
|
16
|
+
const isPersonal = userContext.currentlyActiveGroupId() === userContext.userId;
|
|
17
17
|
const varName = name.replace(/\s+/g, '_');
|
|
18
18
|
const pVar = await (0, peers_sdk_1.PersistentVars)().save({
|
|
19
19
|
persistentVarId: (0, peers_sdk_1.newid)(),
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ColorModePreference } from '../screens/settings/color-mode-dropdown';
|
|
3
|
+
export declare function TabsLayoutApp(props: {
|
|
4
|
+
colorMode?: ColorModePreference;
|
|
5
|
+
}): React.JSX.Element | undefined;
|
|
3
6
|
export declare function TabsLayout(props: {
|
|
7
|
+
userId: string;
|
|
4
8
|
colorMode?: ColorModePreference;
|
|
5
9
|
}): false | React.JSX.Element;
|
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TabsLayoutApp = TabsLayoutApp;
|
|
36
37
|
exports.TabsLayout = TabsLayout;
|
|
37
38
|
const peers_sdk_1 = require("@peers-app/peers-sdk");
|
|
38
39
|
const react_1 = __importStar(require("react"));
|
|
@@ -48,7 +49,28 @@ const system_apps_1 = require("../system-apps");
|
|
|
48
49
|
const routes_loader_1 = require("../ui-router/routes-loader");
|
|
49
50
|
const ui_loader_1 = require("../ui-router/ui-loader");
|
|
50
51
|
const tabs_state_1 = require("./tabs-state");
|
|
52
|
+
function TabsLayoutApp(props) {
|
|
53
|
+
const userId = (0, hooks_1.usePromise)(async () => {
|
|
54
|
+
const _userId = await peers_sdk_1.rpcServerCalls.getUserId();
|
|
55
|
+
return _userId || null;
|
|
56
|
+
});
|
|
57
|
+
if (userId === undefined) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
document.getElementById('appLoadingDiv')?.remove();
|
|
61
|
+
if (!userId) {
|
|
62
|
+
return react_1.default.createElement(setup_user_1.SetupUser, null);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return react_1.default.createElement(TabsLayout, { userId: userId, colorMode: props.colorMode });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let userContextInitialized = false;
|
|
51
69
|
function TabsLayout(props) {
|
|
70
|
+
if (!userContextInitialized) {
|
|
71
|
+
(0, peers_sdk_1.setDefaultClientUserContext)(props.userId);
|
|
72
|
+
userContextInitialized = true;
|
|
73
|
+
}
|
|
52
74
|
const loaded = (0, hooks_1.usePromise)(async () => {
|
|
53
75
|
await (0, globals_1.loadGlobals)().then(() => console.log('Globals loaded'));
|
|
54
76
|
await (0, routes_loader_1.loadAllRoutes)().then(() => console.log('Routes loaded'));
|
|
@@ -62,7 +84,6 @@ function TabsLayout(props) {
|
|
|
62
84
|
});
|
|
63
85
|
if (!loaded)
|
|
64
86
|
return false;
|
|
65
|
-
document.getElementById('appLoadingDiv')?.remove();
|
|
66
87
|
if (globals_1.me.name === globals_1.me.userId) {
|
|
67
88
|
return react_1.default.createElement(setup_user_1.SetupUser, null);
|
|
68
89
|
}
|
|
@@ -79,9 +100,9 @@ function TabsLayoutInternal() {
|
|
|
79
100
|
(0, react_1.useEffect)(() => {
|
|
80
101
|
let sub;
|
|
81
102
|
(0, peers_sdk_1.getUserContext)().then(userContext => {
|
|
82
|
-
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId
|
|
103
|
+
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
|
|
83
104
|
sub = userContext.currentlyActiveGroupId.subscribe(async (groupId) => {
|
|
84
|
-
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId
|
|
105
|
+
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
|
|
85
106
|
// below reloading logic is a kludge to deal with different groups having different packages installed
|
|
86
107
|
await (0, peers_sdk_1.sleep)(100);
|
|
87
108
|
window.location.reload();
|
|
@@ -21,5 +21,4 @@ export declare const allPackages: import("@peers-app/peers-sdk").Observable<{
|
|
|
21
21
|
uiBundleFileId?: string | undefined;
|
|
22
22
|
uiBundleFileHash?: string | undefined;
|
|
23
23
|
}[]>;
|
|
24
|
-
export declare const allRoutesLoaded: import("@peers-app/peers-sdk").Observable<boolean>;
|
|
25
24
|
export declare const loadAllRoutes: () => Promise<true | undefined>;
|
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadAllRoutes = exports.
|
|
3
|
+
exports.loadAllRoutes = exports.allPackages = void 0;
|
|
4
4
|
const peers_sdk_1 = require("@peers-app/peers-sdk");
|
|
5
5
|
require("../ui-defaults");
|
|
6
6
|
exports.allPackages = (0, peers_sdk_1.observable)([]);
|
|
7
|
-
|
|
8
|
-
(0, peers_sdk_1.Packages)().dataChanged.subscribe(async (evt) => {
|
|
9
|
-
if (!(0, exports.allRoutesLoaded)())
|
|
10
|
-
return;
|
|
11
|
-
const _allPackages = (0, exports.allPackages)();
|
|
12
|
-
if (evt.op === 'insert') {
|
|
13
|
-
_allPackages.push(evt.dataObject);
|
|
14
|
-
}
|
|
15
|
-
else if (evt.op === 'delete') {
|
|
16
|
-
let idx = (0, exports.allPackages)().findIndex(p => p.packageId === evt.dataObject.packageId);
|
|
17
|
-
if (idx >= 0) {
|
|
18
|
-
_allPackages.splice(idx, 1);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
let idx = (0, exports.allPackages)().findIndex(p => p.packageId === evt.dataObject.packageId);
|
|
23
|
-
if (idx >= 0) {
|
|
24
|
-
_allPackages[idx] = evt.dataObject;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
(0, exports.allPackages)([..._allPackages]);
|
|
28
|
-
});
|
|
7
|
+
let allRoutesLoaded = false;
|
|
29
8
|
const loadAllRoutes = async () => {
|
|
30
|
-
if (
|
|
9
|
+
if (allRoutesLoaded)
|
|
31
10
|
return;
|
|
11
|
+
allRoutesLoaded = true;
|
|
32
12
|
// Filter packages that have UI bundles (routesBundleFileId or uiBundleFileId)
|
|
33
13
|
let packagesWithUI = await (0, peers_sdk_1.Packages)().list({
|
|
34
14
|
disabled: { $ne: true },
|
|
@@ -36,7 +16,32 @@ const loadAllRoutes = async () => {
|
|
|
36
16
|
});
|
|
37
17
|
(0, exports.allPackages)(packagesWithUI);
|
|
38
18
|
await Promise.all(packagesWithUI.map(pkg => loadRoutesBundle(pkg)));
|
|
39
|
-
(0,
|
|
19
|
+
(0, peers_sdk_1.Packages)().dataChanged.subscribe(async (evt) => {
|
|
20
|
+
const _allPackages = (0, exports.allPackages)();
|
|
21
|
+
if (evt.op === 'insert') {
|
|
22
|
+
_allPackages.push(evt.dataObject);
|
|
23
|
+
}
|
|
24
|
+
else if (evt.op === 'delete') {
|
|
25
|
+
let idx = (0, exports.allPackages)().findIndex(p => p.packageId === evt.dataObject.packageId);
|
|
26
|
+
if (idx >= 0) {
|
|
27
|
+
_allPackages.splice(idx, 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
let idx = (0, exports.allPackages)().findIndex(p => p.packageId === evt.dataObject.packageId);
|
|
32
|
+
if (idx >= 0) {
|
|
33
|
+
_allPackages[idx] = evt.dataObject;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
(0, exports.allPackages)([..._allPackages]);
|
|
37
|
+
});
|
|
38
|
+
(0, peers_sdk_1.Packages)().dataChanged.subscribe(evt => {
|
|
39
|
+
const pkg = evt.dataObject;
|
|
40
|
+
const loadingPromise = routeLoadingPromises[pkg.packageId];
|
|
41
|
+
if (!loadingPromise)
|
|
42
|
+
return;
|
|
43
|
+
reloadPackage(pkg.packageId);
|
|
44
|
+
});
|
|
40
45
|
return true;
|
|
41
46
|
};
|
|
42
47
|
exports.loadAllRoutes = loadAllRoutes;
|
|
@@ -88,10 +93,3 @@ const reloadPackage = (0, peers_sdk_1.debounceByArgs)(async (packageId) => {
|
|
|
88
93
|
await loadRoutesBundle(pkg, true);
|
|
89
94
|
}
|
|
90
95
|
}, 200);
|
|
91
|
-
(0, peers_sdk_1.Packages)().dataChanged.subscribe(evt => {
|
|
92
|
-
const pkg = evt.dataObject;
|
|
93
|
-
const loadingPromise = routeLoadingPromises[pkg.packageId];
|
|
94
|
-
if (!loadingPromise)
|
|
95
|
-
return;
|
|
96
|
-
reloadPackage(pkg.packageId);
|
|
97
|
-
});
|