@jinion/cli 0.0.0-stage → 0.3.491
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/bin/jinion.js +4 -0
- package/dist/app/activity.js +50 -0
- package/dist/app/activity.js.map +1 -0
- package/dist/app/announcements.js +21 -0
- package/dist/app/announcements.js.map +1 -0
- package/dist/app/api.js +26 -0
- package/dist/app/api.js.map +1 -0
- package/dist/app/app.js +91 -0
- package/dist/app/app.js.map +1 -0
- package/dist/app/aside.js +52 -0
- package/dist/app/aside.js.map +1 -0
- package/dist/app/dialogs.js +43 -0
- package/dist/app/dialogs.js.map +1 -0
- package/dist/app/keys.js +79 -0
- package/dist/app/keys.js.map +1 -0
- package/dist/app/prompt-area.js +56 -0
- package/dist/app/prompt-area.js.map +1 -0
- package/dist/app/shortcuts.js +31 -0
- package/dist/app/shortcuts.js.map +1 -0
- package/dist/app/sidebar.js +50 -0
- package/dist/app/sidebar.js.map +1 -0
- package/dist/app/status-line.js +23 -0
- package/dist/app/status-line.js.map +1 -0
- package/dist/app/task-line.js +19 -0
- package/dist/app/task-line.js.map +1 -0
- package/dist/app/use-screen.js +24 -0
- package/dist/app/use-screen.js.map +1 -0
- package/dist/app/views.js +62 -0
- package/dist/app/views.js.map +1 -0
- package/dist/main.js +122 -0
- package/dist/main.js.map +1 -0
- package/dist/panels/account/account-picker.js +118 -0
- package/dist/panels/account/account-picker.js.map +1 -0
- package/dist/panels/account/describe.js +14 -0
- package/dist/panels/account/describe.js.map +1 -0
- package/dist/panels/account/sign-in-view.js +8 -0
- package/dist/panels/account/sign-in-view.js.map +1 -0
- package/dist/panels/account/use-sign-in.js +46 -0
- package/dist/panels/account/use-sign-in.js.map +1 -0
- package/dist/panels/context.js +55 -0
- package/dist/panels/context.js.map +1 -0
- package/dist/panels/diff/change-list.js +48 -0
- package/dist/panels/diff/change-list.js.map +1 -0
- package/dist/panels/diff/current-view.js +47 -0
- package/dist/panels/diff/current-view.js.map +1 -0
- package/dist/panels/diff/diff-panel.js +22 -0
- package/dist/panels/diff/diff-panel.js.map +1 -0
- package/dist/panels/diff/file-diff.js +19 -0
- package/dist/panels/diff/file-diff.js.map +1 -0
- package/dist/panels/diff/views.js +29 -0
- package/dist/panels/diff/views.js.map +1 -0
- package/dist/panels/feedback.js +67 -0
- package/dist/panels/feedback.js.map +1 -0
- package/dist/panels/help.js +79 -0
- package/dist/panels/help.js.map +1 -0
- package/dist/panels/mcp.js +129 -0
- package/dist/panels/mcp.js.map +1 -0
- package/dist/panels/memory.js +55 -0
- package/dist/panels/memory.js.map +1 -0
- package/dist/panels/mode.js +36 -0
- package/dist/panels/mode.js.map +1 -0
- package/dist/panels/model.js +20 -0
- package/dist/panels/model.js.map +1 -0
- package/dist/panels/onboarding/onboarding-panel.js +56 -0
- package/dist/panels/onboarding/onboarding-panel.js.map +1 -0
- package/dist/panels/onboarding/use-onboarding.js +65 -0
- package/dist/panels/onboarding/use-onboarding.js.map +1 -0
- package/dist/panels/profile.js +31 -0
- package/dist/panels/profile.js.map +1 -0
- package/dist/panels/resume.js +52 -0
- package/dist/panels/resume.js.map +1 -0
- package/dist/panels/rewind/changes.js +20 -0
- package/dist/panels/rewind/changes.js.map +1 -0
- package/dist/panels/rewind/rewind-panel.js +93 -0
- package/dist/panels/rewind/rewind-panel.js.map +1 -0
- package/dist/panels/sign-in/sign-in-panel.js +56 -0
- package/dist/panels/sign-in/sign-in-panel.js.map +1 -0
- package/dist/panels/sign-in/use-jinion-sign-in.js +69 -0
- package/dist/panels/sign-in/use-jinion-sign-in.js.map +1 -0
- package/dist/panels/statusline.js +94 -0
- package/dist/panels/statusline.js.map +1 -0
- package/dist/panels/tasks/output.js +23 -0
- package/dist/panels/tasks/output.js.map +1 -0
- package/dist/panels/tasks/task-output.js +29 -0
- package/dist/panels/tasks/task-output.js.map +1 -0
- package/dist/panels/tasks/tasks-panel.js +75 -0
- package/dist/panels/tasks/tasks-panel.js.map +1 -0
- package/dist/panels/terminal-setup.js +41 -0
- package/dist/panels/terminal-setup.js.map +1 -0
- package/dist/panels/usage/section.js +16 -0
- package/dist/panels/usage/section.js.map +1 -0
- package/dist/panels/usage/stats-view.js +52 -0
- package/dist/panels/usage/stats-view.js.map +1 -0
- package/dist/panels/usage/usage-panel.js +68 -0
- package/dist/panels/usage/usage-panel.js.map +1 -0
- package/dist/panels/usage/usage-view.js +51 -0
- package/dist/panels/usage/usage-view.js.map +1 -0
- package/dist/prompt/attachments.js +91 -0
- package/dist/prompt/attachments.js.map +1 -0
- package/dist/prompt/draft.js +24 -0
- package/dist/prompt/draft.js.map +1 -0
- package/dist/prompt/images.js +84 -0
- package/dist/prompt/images.js.map +1 -0
- package/dist/prompt/pasted-path.js +19 -0
- package/dist/prompt/pasted-path.js.map +1 -0
- package/dist/prompt/use-prompt.js +62 -0
- package/dist/prompt/use-prompt.js.map +1 -0
- package/dist/serve.js +38 -0
- package/dist/serve.js.map +1 -0
- package/dist/state/session.js +91 -0
- package/dist/state/session.js.map +1 -0
- package/dist/status/data.js +39 -0
- package/dist/status/data.js.map +1 -0
- package/dist/status/git.js +18 -0
- package/dist/status/git.js.map +1 -0
- package/dist/status/items.js +8 -0
- package/dist/status/items.js.map +1 -0
- package/dist/status/line.js +25 -0
- package/dist/status/line.js.map +1 -0
- package/dist/status/saved.js +8 -0
- package/dist/status/saved.js.map +1 -0
- package/dist/status/segment.js +2 -0
- package/dist/status/segment.js.map +1 -0
- package/dist/status/segments/conversation.js +71 -0
- package/dist/status/segments/conversation.js.map +1 -0
- package/dist/status/segments/git.js +33 -0
- package/dist/status/segments/git.js.map +1 -0
- package/dist/status/segments/identity.js +71 -0
- package/dist/status/segments/identity.js.map +1 -0
- package/dist/status/segments/index.js +27 -0
- package/dist/status/segments/index.js.map +1 -0
- package/dist/status/segments/usage.js +61 -0
- package/dist/status/segments/usage.js.map +1 -0
- package/dist/terminal/apple-terminal.js +68 -0
- package/dist/terminal/apple-terminal.js.map +1 -0
- package/dist/ui/banner.js +24 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/entries/changes-card.js +27 -0
- package/dist/ui/entries/changes-card.js.map +1 -0
- package/dist/ui/entries/entry-view.js +82 -0
- package/dist/ui/entries/entry-view.js.map +1 -0
- package/dist/ui/entries/status-entries.js +33 -0
- package/dist/ui/entries/status-entries.js.map +1 -0
- package/dist/ui/entries/tools/agent-view.js +39 -0
- package/dist/ui/entries/tools/agent-view.js.map +1 -0
- package/dist/ui/entries/tools/mcp-view.js +10 -0
- package/dist/ui/entries/tools/mcp-view.js.map +1 -0
- package/dist/ui/entries/tools/result-preview.js +19 -0
- package/dist/ui/entries/tools/result-preview.js.map +1 -0
- package/dist/ui/entries/tools/search.js +42 -0
- package/dist/ui/entries/tools/search.js.map +1 -0
- package/dist/ui/entries/tools/shell-footer.js +36 -0
- package/dist/ui/entries/tools/shell-footer.js.map +1 -0
- package/dist/ui/entries/tools/tool-view.js +47 -0
- package/dist/ui/entries/tools/tool-view.js.map +1 -0
- package/dist/ui/entries/tools/web.js +41 -0
- package/dist/ui/entries/tools/web.js.map +1 -0
- package/dist/ui/modes.js +13 -0
- package/dist/ui/modes.js.map +1 -0
- package/dist/ui/task-marks.js +7 -0
- package/dist/ui/task-marks.js.map +1 -0
- package/dist/ui/use-async.js +17 -0
- package/dist/ui/use-async.js.map +1 -0
- package/dist/ui/use-pager.js +25 -0
- package/dist/ui/use-pager.js.map +1 -0
- package/dist/ui/use-project-files.js +18 -0
- package/dist/ui/use-project-files.js.map +1 -0
- package/dist/ui/use-workdir.js +9 -0
- package/dist/ui/use-workdir.js.map +1 -0
- package/package.json +34 -3
- package/README.md +0 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, ChoiceList, Panel, PromptInput, Text, useChoiceList, useInput, useTheme } from '@jinion/tui';
|
|
3
|
+
import { useApi } from '../../app/api.js';
|
|
4
|
+
import { useOnboarding } from './use-onboarding.js';
|
|
5
|
+
/** In the prompt's place once someone signed in, until their account is active. */
|
|
6
|
+
export function OnboardingPanel() {
|
|
7
|
+
const api = useApi();
|
|
8
|
+
const theme = useTheme();
|
|
9
|
+
const onboarding = useOnboarding();
|
|
10
|
+
const { questions, step } = onboarding;
|
|
11
|
+
const question = step.kind === 'question' ? questions?.[step.index] : undefined;
|
|
12
|
+
useInput((input, key) => {
|
|
13
|
+
if (key.ctrl && input === 'c')
|
|
14
|
+
return api.quit();
|
|
15
|
+
if (key.escape)
|
|
16
|
+
onboarding.back();
|
|
17
|
+
});
|
|
18
|
+
if (step.kind === 'code' || !questions) {
|
|
19
|
+
return (_jsxs(Panel, { title: "You\u2019re almost in", header: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.muted, children: "Jinion is invite-only during the beta. Enter the invite code you were given." }), _jsx(Text, { color: theme.muted, children: "While you use it, Jinion sends how your turns go and the errors it hits, never your conversations. /telemetry turns this off." })] }), hints: [
|
|
20
|
+
['Enter', 'continue'],
|
|
21
|
+
['Ctrl+C', 'quit'],
|
|
22
|
+
], children: [step.kind === 'code' && step.problem && _jsx(Text, { color: theme.error, children: step.problem }), step.kind === 'code' && step.checking ? (_jsx(Text, { color: theme.muted, children: "Checking your invite\u2026" })) : (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "invite code: " }), _jsx(PromptInput, { value: step.kind === 'code' ? step.code : '', onChange: onboarding.typeCode, onSubmit: onboarding.checkCode, placeholder: "JIN-XXXX-XXXX", paddingX: 0 })] }))] }));
|
|
23
|
+
}
|
|
24
|
+
if (step.kind === 'finishing' || !question) {
|
|
25
|
+
return (_jsx(Panel, { title: "You\u2019re almost in", children: _jsx(Text, { color: theme.muted, children: "Setting up your account\u2026" }) }));
|
|
26
|
+
}
|
|
27
|
+
return (_jsxs(Panel, { title: "A few questions", subtitle: `${step.index + 1} of ${questions.length}`, header: _jsx(Text, { color: theme.muted, children: "They help us make Jinion better for you." }), hints: hintsOf(question), children: [_jsxs(Text, { bold: true, children: [question.prompt, !question.required && _jsx(Text, { color: theme.muted, children: " (optional)" })] }), question.hint && _jsx(Text, { color: theme.muted, children: question.hint }), step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: question.kind === 'text' ? (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: '> ' }), _jsx(PromptInput, { value: String(onboarding.answers[question.id] ?? ''), onChange: (value) => onboarding.typeAnswer(question, value), onSubmit: (value) => onboarding.answer(question, step.index, value.trim()), placeholder: question.required ? 'Your answer' : 'Your answer, or Enter to skip', paddingX: 0 })] })) : (_jsx(Options, { question: question, chosen: onboarding.answers[question.id], onAnswer: (value) => onboarding.answer(question, step.index, value) }, question.id)) })] }));
|
|
28
|
+
}
|
|
29
|
+
/** One of the options for `choice`, any of them for `choices`; keyed by its question, so each starts afresh. */
|
|
30
|
+
function Options({ question, chosen, onAnswer }) {
|
|
31
|
+
const multiple = question.kind === 'choices';
|
|
32
|
+
const list = useChoiceList({
|
|
33
|
+
keys: question.options,
|
|
34
|
+
mode: multiple ? 'multiple' : 'single',
|
|
35
|
+
initialFocus: typeof chosen === 'string' ? chosen : undefined,
|
|
36
|
+
initialChecked: Array.isArray(chosen) ? chosen : [],
|
|
37
|
+
onCancel: () => { },
|
|
38
|
+
onSubmit: (picked) => onAnswer(multiple ? picked : (picked[0] ?? '')),
|
|
39
|
+
});
|
|
40
|
+
return _jsx(ChoiceList, { list: list, limit: question.options.length, choices: question.options.map((option) => ({ key: option, label: option })) });
|
|
41
|
+
}
|
|
42
|
+
function hintsOf(question) {
|
|
43
|
+
if (question.kind === 'choices') {
|
|
44
|
+
return [
|
|
45
|
+
['Space', 'pick'],
|
|
46
|
+
['Enter', 'continue'],
|
|
47
|
+
['Esc', 'back'],
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
return [
|
|
51
|
+
['Enter', 'continue'],
|
|
52
|
+
...(question.kind === 'choice' ? [['Up/Down', 'move']] : []),
|
|
53
|
+
['Esc', 'back'],
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=onboarding-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-panel.js","sourceRoot":"","sources":["../../../src/panels/onboarding/onboarding-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { errorMessage } from '@jinion/core/lib/errors';
|
|
3
|
+
import { useApi } from '../../app/api.js';
|
|
4
|
+
/**
|
|
5
|
+
* An account signed in but not active yet goes through here: an invite code, then the questions the dashboard asks.
|
|
6
|
+
* Nothing here says it worked: the app's `jinionUser` field turns active, and the app draws itself in its place.
|
|
7
|
+
*/
|
|
8
|
+
export function useOnboarding() {
|
|
9
|
+
const api = useApi();
|
|
10
|
+
const [questions, setQuestions] = useState();
|
|
11
|
+
const [step, setStep] = useState({ kind: 'code', code: '' });
|
|
12
|
+
const [answers, setAnswers] = useState({});
|
|
13
|
+
const [code, setCode] = useState('');
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
api.request('jinion/onboarding', {}).then(setQuestions, () => setQuestions([]));
|
|
16
|
+
}, []);
|
|
17
|
+
const finish = (all, withCode) => {
|
|
18
|
+
setStep({ kind: 'finishing' });
|
|
19
|
+
void api.request('jinion/activate', { code: withCode, answers: all }).catch((error) => {
|
|
20
|
+
const last = (questions?.length ?? 0) - 1;
|
|
21
|
+
setStep(last < 0 ? { kind: 'code', code: withCode, problem: errorMessage(error) } : { kind: 'question', index: last, problem: errorMessage(error) });
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
// The code comes along: state set a moment before isn't read back yet.
|
|
25
|
+
const next = (index, all = answers, withCode = code) => {
|
|
26
|
+
if (questions && index < questions.length)
|
|
27
|
+
return setStep({ kind: 'question', index });
|
|
28
|
+
finish(all, withCode);
|
|
29
|
+
};
|
|
30
|
+
const checkCode = (typed) => {
|
|
31
|
+
const trimmed = typed.trim();
|
|
32
|
+
// Without the questions yet, an empty set of answers would go along.
|
|
33
|
+
if (!trimmed || !questions)
|
|
34
|
+
return;
|
|
35
|
+
setStep({ kind: 'code', code: trimmed, checking: true });
|
|
36
|
+
void api.request('jinion/check-invite', { code: trimmed }).then(() => {
|
|
37
|
+
setCode(trimmed);
|
|
38
|
+
next(0, answers, trimmed);
|
|
39
|
+
}, (error) => setStep({ kind: 'code', code: trimmed, problem: errorMessage(error) }));
|
|
40
|
+
};
|
|
41
|
+
/** Moves on once a required question has its answer. */
|
|
42
|
+
const answer = (question, index, value) => {
|
|
43
|
+
const all = { ...answers, [question.id]: value };
|
|
44
|
+
setAnswers(all);
|
|
45
|
+
if (question.required && value.length === 0)
|
|
46
|
+
return setStep({ kind: 'question', index, problem: 'Please answer this one to continue.' });
|
|
47
|
+
next(index + 1, all);
|
|
48
|
+
};
|
|
49
|
+
const back = () => {
|
|
50
|
+
if (step.kind !== 'question')
|
|
51
|
+
return;
|
|
52
|
+
setStep(step.index === 0 ? { kind: 'code', code } : { kind: 'question', index: step.index - 1 });
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
questions,
|
|
56
|
+
step,
|
|
57
|
+
answers,
|
|
58
|
+
typeCode: (typed) => setStep({ kind: 'code', code: typed }),
|
|
59
|
+
checkCode,
|
|
60
|
+
typeAnswer: (question, value) => setAnswers({ ...answers, [question.id]: value }),
|
|
61
|
+
answer,
|
|
62
|
+
back,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=use-onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-onboarding.js","sourceRoot":"","sources":["../../../src/panels/onboarding/use-onboarding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, ChoiceList, Panel, Text, useChoiceList, usePanel, useTheme } from '@jinion/tui';
|
|
3
|
+
import { useAtomValue } from 'jotai';
|
|
4
|
+
import { useApi } from '../app/api.js';
|
|
5
|
+
import { jinionUserAtom } from '../state/session.js';
|
|
6
|
+
import { useAsync } from '../ui/use-async.js';
|
|
7
|
+
export function ProfilePanel() {
|
|
8
|
+
const api = useApi();
|
|
9
|
+
const theme = useTheme();
|
|
10
|
+
const { close } = usePanel();
|
|
11
|
+
const user = useAtomValue(jinionUserAtom);
|
|
12
|
+
const invites = useAsync(() => api.request('jinion/invites', {}), []);
|
|
13
|
+
// Closed first: signing out puts the app's sign-in in place of everything, and this panel shouldn't wait under it.
|
|
14
|
+
const list = useChoiceList({
|
|
15
|
+
keys: ['sign-out'],
|
|
16
|
+
mode: 'single',
|
|
17
|
+
onCancel: close,
|
|
18
|
+
onSubmit: () => {
|
|
19
|
+
close();
|
|
20
|
+
api.act(api.request('jinion/sign-out', {}));
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (!user)
|
|
24
|
+
return null;
|
|
25
|
+
return (_jsxs(Panel, { title: "Profile", hints: [
|
|
26
|
+
['Enter', 'sign out'],
|
|
27
|
+
['Esc', 'close'],
|
|
28
|
+
], children: [_jsxs(Text, { children: ["Signed in as ", _jsx(Text, { bold: true, children: user.name ?? user.email }), user.name && _jsxs(Text, { color: theme.muted, children: [" (", user.email, ")"] })] }), _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Invites" }), _jsx(Text, { color: theme.muted, children: "Jinion is invite-only during the beta. Each of your codes lets one person in." }), invites.state === 'pending' && _jsx(Text, { color: theme.muted, children: "Getting your codes\u2026" }), invites.state === 'failed' && _jsxs(Text, { color: theme.muted, children: ["Couldn\u2019t get your codes: ", invites.error] }), invites.state === 'done' &&
|
|
29
|
+
invites.value.map((invite) => (_jsx(Text, { children: invite.status === 'active' ? (invite.code) : (_jsxs(Text, { color: theme.muted, children: [invite.code, " ", invite.status === 'used' ? (invite.usedBy ? `used by ${invite.usedBy}` : 'used') : 'no longer works'] })) }, invite.code)))] }), _jsx(ChoiceList, { list: list, limit: 1, choices: [{ key: 'sign-out', label: 'Sign out', description: 'You’ll need to sign in again to keep using Jinion' }] })] }));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/panels/profile.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { Box, fuzzyFilter, Highlight, ListRow, Panel, PromptInput, SelectList, Text, useInput, useListNavigation, usePanel, useTheme, useWindowSize } from '@jinion/tui';
|
|
4
|
+
import { useAtomValue } from 'jotai';
|
|
5
|
+
import { ago } from '@jinion/core/lib/format';
|
|
6
|
+
import { useApi } from '../app/api.js';
|
|
7
|
+
import { sessionAtom } from '../state/session.js';
|
|
8
|
+
import { useAsync } from '../ui/use-async.js';
|
|
9
|
+
const CHROME_ROWS = 9;
|
|
10
|
+
const ROWS_PER_SESSION = 2;
|
|
11
|
+
export function ResumePanel({ query: initialQuery = '' }) {
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
const api = useApi();
|
|
14
|
+
const { close } = usePanel();
|
|
15
|
+
const { rows } = useWindowSize();
|
|
16
|
+
const { id: current } = useAtomValue(sessionAtom);
|
|
17
|
+
const [query, setQuery] = useState(initialQuery.trim());
|
|
18
|
+
const saved = useAsync(() => api.request('saved/list', {}), [current]);
|
|
19
|
+
const sessions = useMemo(() => (saved.state === 'done' ? saved.value.filter((session) => session.id !== current) : []), [saved, current]);
|
|
20
|
+
const matches = useMemo(() => fuzzyFilter(sessions, query, (session) => session.title), [sessions, query]);
|
|
21
|
+
const limit = Math.max(1, Math.floor((rows - CHROME_ROWS) / ROWS_PER_SESSION));
|
|
22
|
+
const [selected, setSelected] = useListNavigation(matches.length, { wrap: false, pageSize: limit });
|
|
23
|
+
useEffect(() => setSelected(0), [query, setSelected]);
|
|
24
|
+
useInput((_, key) => {
|
|
25
|
+
if (key.escape)
|
|
26
|
+
close();
|
|
27
|
+
});
|
|
28
|
+
const choose = () => {
|
|
29
|
+
const match = matches[selected];
|
|
30
|
+
if (!match)
|
|
31
|
+
return;
|
|
32
|
+
close();
|
|
33
|
+
// The conversation shown stays open in its tab.
|
|
34
|
+
api.act(api.request('sessions/open', { resume: match.item.id, activate: true }));
|
|
35
|
+
};
|
|
36
|
+
return (_jsx(Panel, { title: "Resume", subtitle: `${sessions.length} conversations`, grow: true, header: _jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "search " }), _jsx(PromptInput, { value: query, onChange: setQuery, onSubmit: choose, placeholder: "Type to filter", paddingX: 0 })] }), hints: [
|
|
37
|
+
['Enter', 'resume'],
|
|
38
|
+
['Up/Down', 'move'],
|
|
39
|
+
['PgUp/PgDn', 'page'],
|
|
40
|
+
['Esc', 'close'],
|
|
41
|
+
], children: _jsx(SelectList, { items: matches, selected: selected, limit: limit, empty: saved.state === 'pending'
|
|
42
|
+
? 'Reading saved conversations…'
|
|
43
|
+
: saved.state === 'failed'
|
|
44
|
+
? `Couldn't read saved conversations: ${saved.error}`
|
|
45
|
+
: sessions.length === 0
|
|
46
|
+
? 'No saved conversations yet'
|
|
47
|
+
: 'No conversations match', renderItem: ({ item, positions }, state) => (_jsx(ListRow, { selected: state.selected, label: _jsx(Highlight, { text: item.title, positions: positions }), aside: ago(item.updatedAt), detail: describe(item) })) }) }));
|
|
48
|
+
}
|
|
49
|
+
function describe({ openElsewhere, worktree, messages, firstPrompt = '' }) {
|
|
50
|
+
return `${openElsewhere ? 'open in another jinion · ' : ''}${worktree ? `worktree ${worktree} · ` : ''}${messages} messages · "${firstPrompt}"`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/panels/resume.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzK,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,EAAE,EAAsB;IAC1E,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,CAAC;IACjC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAExD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1I,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAC3G,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAEpG,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;IAEtD,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;QAClB,IAAI,GAAG,CAAC,MAAM;YAAE,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,KAAK,EAAE,CAAC;QACR,gDAAgD;QAChD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,KAAK,IACJ,KAAK,EAAC,QAAQ,EACd,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,gBAAgB,EAC5C,IAAI,QACJ,MAAM,EACJ,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,wBAAgB,EACxC,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAC,gBAAgB,EAAC,QAAQ,EAAE,CAAC,GAAI,IACzG,EAER,KAAK,EAAE;YACL,CAAC,OAAO,EAAE,QAAQ,CAAC;YACnB,CAAC,SAAS,EAAE,MAAM,CAAC;YACnB,CAAC,WAAW,EAAE,MAAM,CAAC;YACrB,CAAC,KAAK,EAAE,OAAO,CAAC;SACjB,YAED,KAAC,UAAU,IACT,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,KAAK,EACH,KAAK,CAAC,KAAK,KAAK,SAAS;gBACvB,CAAC,CAAC,8BAA8B;gBAChC,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ;oBACxB,CAAC,CAAC,sCAAsC,KAAK,CAAC,KAAK,EAAE;oBACrD,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;wBACrB,CAAC,CAAC,4BAA4B;wBAC9B,CAAC,CAAC,wBAAwB,EAElC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1C,KAAC,OAAO,IACN,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,KAAK,EAAE,KAAC,SAAS,IAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,GAAI,EAC5D,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAC1B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GACtB,CACH,GACD,GACI,CACT,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAG,EAAE,EAAgB;IACrF,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,gBAAgB,WAAW,GAAG,CAAC;AAClJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { relative } from 'node:path';
|
|
3
|
+
import { Box, Text, useTheme } from '@jinion/tui';
|
|
4
|
+
import { plural } from '@jinion/core/lib/format';
|
|
5
|
+
import { useAsync } from '../../ui/use-async.js';
|
|
6
|
+
import { useWorkdir } from '../../ui/use-workdir.js';
|
|
7
|
+
const FILES_SHOWN = 3;
|
|
8
|
+
export function Changes({ changes, indent }) {
|
|
9
|
+
const cwd = useWorkdir();
|
|
10
|
+
const theme = useTheme();
|
|
11
|
+
const known = useAsync(() => changes, [changes]);
|
|
12
|
+
if (known.state !== 'done' || !known.value) {
|
|
13
|
+
return (_jsx(Box, { paddingLeft: indent, children: _jsx(Text, { color: theme.muted, children: known.state === 'pending' ? 'Checking what would change…' : 'No file changes since then' }) }));
|
|
14
|
+
}
|
|
15
|
+
const { files, insertions, deletions } = known.value;
|
|
16
|
+
const names = files.slice(0, FILES_SHOWN).map((file) => relative(cwd, file) || file);
|
|
17
|
+
const more = files.length - names.length;
|
|
18
|
+
return (_jsxs(Box, { paddingLeft: indent, flexDirection: "column", children: [_jsxs(Text, { children: [files.length === 1 ? '1 file changes' : `${plural(files.length, 'file')} change`, _jsxs(Text, { color: theme.diff.added, children: [" +", insertions] }), _jsxs(Text, { color: theme.diff.removed, children: [" -", deletions] })] }), _jsxs(Text, { color: theme.muted, wrap: "truncate-end", children: [names.join(', '), more > 0 ? ` … ${more} more` : ''] })] }));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.js","sourceRoot":"","sources":["../../../src/panels/rewind/changes.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAiE;IACxG,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjD,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3C,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAE,MAAM,YACtB,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,YAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,4BAA4B,GAAQ,GACvH,CACP,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAEzC,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAC,QAAQ,aAC9C,MAAC,IAAI,eACF,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EACjF,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,mBAAK,UAAU,IAAQ,EACpD,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,mBAAK,SAAS,IAAQ,IAChD,EACP,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAC,cAAc,aAC1C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAChB,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAC7B,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { ChoiceList, choiceIndent, Panel, Text, useChoiceList, usePanel, useTheme } from '@jinion/tui';
|
|
4
|
+
import { plural } from '@jinion/core/lib/format';
|
|
5
|
+
import { firstFilledLine as firstLine } from '@jinion/core/lib/text';
|
|
6
|
+
import { useAsync } from '../../ui/use-async.js';
|
|
7
|
+
import { Changes } from './changes.js';
|
|
8
|
+
const VISIBLE = 8;
|
|
9
|
+
export function RewindPanel({ points, preview, onRewind }) {
|
|
10
|
+
const [picked, setPicked] = useState();
|
|
11
|
+
// Each preview asks the agent once, however often the focus comes back to it.
|
|
12
|
+
const previews = useRef(new Map());
|
|
13
|
+
const previewOf = (point) => {
|
|
14
|
+
let changes = previews.current.get(point.promptId);
|
|
15
|
+
if (!changes) {
|
|
16
|
+
changes = preview(point).catch(() => undefined);
|
|
17
|
+
previews.current.set(point.promptId, changes);
|
|
18
|
+
}
|
|
19
|
+
return changes;
|
|
20
|
+
};
|
|
21
|
+
return picked ? (_jsx(ScopeStep, { point: picked, changes: previewOf(picked), onBack: () => setPicked(undefined), onPick: (scope) => onRewind(picked, scope) })) : (_jsx(PointStep, { points: points, previewOf: previewOf, onPick: setPicked }));
|
|
22
|
+
}
|
|
23
|
+
function PointStep({ points, previewOf, onPick }) {
|
|
24
|
+
const { close } = usePanel();
|
|
25
|
+
const list = useChoiceList({
|
|
26
|
+
keys: points.map((point) => point.entry),
|
|
27
|
+
mode: 'single',
|
|
28
|
+
onCancel: close,
|
|
29
|
+
onSubmit: ([entry]) => {
|
|
30
|
+
const point = points.find((candidate) => candidate.entry === entry);
|
|
31
|
+
if (point)
|
|
32
|
+
onPick(point);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
// Only the focused message is previewed, so moving through the list asks the agent one message at a time.
|
|
36
|
+
const choices = points.map((point) => ({
|
|
37
|
+
key: point.entry,
|
|
38
|
+
label: firstLine(point.text),
|
|
39
|
+
editor: point.entry === list.focus ? _jsx(Changes, { changes: previewOf(point), indent: choiceIndent(list) }) : undefined,
|
|
40
|
+
}));
|
|
41
|
+
return (_jsx(Panel, { title: "Rewind", subtitle: plural(points.length, 'message'), hints: [
|
|
42
|
+
['Enter', 'pick'],
|
|
43
|
+
['Up/Down', 'move'],
|
|
44
|
+
['Esc', 'cancel'],
|
|
45
|
+
], children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE }) }));
|
|
46
|
+
}
|
|
47
|
+
/** Claude Code's choices, in its words, so they read the same as there. */
|
|
48
|
+
const SCOPES = [
|
|
49
|
+
{
|
|
50
|
+
key: 'both',
|
|
51
|
+
label: 'Restore code and conversation',
|
|
52
|
+
description: 'Files go back, and the conversation goes on from before this message, which goes back into the prompt',
|
|
53
|
+
scope: { code: true, conversation: true },
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
key: 'conversation',
|
|
57
|
+
label: 'Restore conversation',
|
|
58
|
+
description: 'The conversation goes on from before this message; the files stay as they are',
|
|
59
|
+
scope: { code: false, conversation: true },
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
key: 'code',
|
|
63
|
+
label: 'Restore code',
|
|
64
|
+
description: 'Files go back; the conversation goes on as it is',
|
|
65
|
+
scope: { code: true, conversation: false },
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
const NEVER_MIND = { key: 'never-mind', label: 'Never mind', description: 'Back to the messages' };
|
|
69
|
+
function ScopeStep({ point, changes, onBack, onPick }) {
|
|
70
|
+
const theme = useTheme();
|
|
71
|
+
const { close } = usePanel();
|
|
72
|
+
const known = useAsync(() => changes, [changes]);
|
|
73
|
+
// Restoring code is offered only where there are file changes to take back.
|
|
74
|
+
const options = known.state === 'pending' ? [] : [...SCOPES.filter((scope) => (known.state === 'done' && known.value) || !scope.scope.code), NEVER_MIND];
|
|
75
|
+
const list = useChoiceList({
|
|
76
|
+
keys: options.map((option) => option.key),
|
|
77
|
+
mode: 'single',
|
|
78
|
+
onCancel: onBack,
|
|
79
|
+
onSubmit: ([key]) => {
|
|
80
|
+
const scope = SCOPES.find((candidate) => candidate.key === key);
|
|
81
|
+
if (!scope)
|
|
82
|
+
return onBack();
|
|
83
|
+
close();
|
|
84
|
+
onPick(scope.scope);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
return (_jsx(Panel, { title: "Rewind to before", subtitle: firstLine(point.text), header: _jsx(Changes, { changes: changes, indent: 0 }), hints: [
|
|
88
|
+
['Enter', 'rewind'],
|
|
89
|
+
['Up/Down', 'move'],
|
|
90
|
+
['Esc', 'back'],
|
|
91
|
+
], children: _jsx(ChoiceList, { list: list, choices: options.map(({ key, label, description }) => ({ key, label, description: _jsx(Text, { color: theme.muted, children: description }) })) }) }));
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=rewind-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewind-panel.js","sourceRoot":"","sources":["../../../src/panels/rewind/rewind-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, ChoiceList, Panel, PromptInput, Text, useChoiceList, useInput, useTheme } from '@jinion/tui';
|
|
3
|
+
import { useApi } from '../../app/api.js';
|
|
4
|
+
import { useJinionSignIn } from './use-jinion-sign-in.js';
|
|
5
|
+
const WAYS = ['github', 'email'];
|
|
6
|
+
/** In the prompt's place until someone is signed in to Jinion; it can't be closed, only quit. */
|
|
7
|
+
export function SignInPanel() {
|
|
8
|
+
const api = useApi();
|
|
9
|
+
const theme = useTheme();
|
|
10
|
+
const signIn = useJinionSignIn();
|
|
11
|
+
const { step } = signIn;
|
|
12
|
+
const list = useChoiceList({
|
|
13
|
+
keys: WAYS,
|
|
14
|
+
mode: 'single',
|
|
15
|
+
isActive: step.kind === 'choose',
|
|
16
|
+
onCancel: () => { },
|
|
17
|
+
onSubmit: ([way]) => (way === 'github' ? signIn.withGithub() : signIn.withEmail()),
|
|
18
|
+
});
|
|
19
|
+
useInput((input, key) => {
|
|
20
|
+
if (key.ctrl && input === 'c')
|
|
21
|
+
return api.quit();
|
|
22
|
+
if (key.escape && step.kind !== 'choose')
|
|
23
|
+
signIn.back();
|
|
24
|
+
});
|
|
25
|
+
return (_jsxs(Panel, { title: "Welcome to Jinion", header: _jsx(Text, { color: theme.muted, children: "Sign in to get started." }), hints: hintsOf(step), children: [step.kind === 'choose' && (_jsxs(_Fragment, { children: [step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsx(ChoiceList, { list: list, limit: WAYS.length, choices: [
|
|
26
|
+
{ key: 'github', label: 'Continue with GitHub', description: 'Opens your browser' },
|
|
27
|
+
{ key: 'email', label: 'Continue with email', description: 'We’ll send you a 6-digit code' },
|
|
28
|
+
] })] })), step.kind === 'github' && (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Waiting for you to sign in with GitHub in your browser\u2026" }), step.link && (_jsxs(Text, { children: [_jsx(Text, { color: theme.muted, children: "Browser didn\u2019t open? Go to " }), _jsx(Text, { color: theme.code, children: step.link })] }))] })), step.kind === 'email' &&
|
|
29
|
+
(step.sending ? (_jsxs(Text, { color: theme.muted, children: ["Sending your code to ", step.email, "\u2026"] })) : (_jsxs(_Fragment, { children: [step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "email: " }), _jsx(PromptInput, { value: step.email, onChange: signIn.typeEmail, onSubmit: signIn.sendCode, placeholder: "you@example.com", paddingX: 0 })] })] }))), step.kind === 'code' && (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["We sent a 6-digit code to ", _jsx(Text, { bold: true, children: step.email }), ". It\u2019s valid for 10 minutes."] }), step.problem && _jsx(Text, { color: theme.error, children: step.problem }), step.checking ? (_jsx(Text, { color: theme.muted, children: "Checking your code\u2026" })) : (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "code: " }), _jsx(PromptInput, { value: step.code, onChange: signIn.typeCode, onSubmit: signIn.signIn, placeholder: "123456", paddingX: 0 })] }))] }))] }));
|
|
30
|
+
}
|
|
31
|
+
function hintsOf(step) {
|
|
32
|
+
switch (step.kind) {
|
|
33
|
+
case 'choose':
|
|
34
|
+
return [
|
|
35
|
+
['Enter', 'continue'],
|
|
36
|
+
['Up/Down', 'move'],
|
|
37
|
+
['Ctrl+C', 'quit'],
|
|
38
|
+
];
|
|
39
|
+
case 'github':
|
|
40
|
+
return [
|
|
41
|
+
['Esc', 'back'],
|
|
42
|
+
['Ctrl+C', 'quit'],
|
|
43
|
+
];
|
|
44
|
+
case 'email':
|
|
45
|
+
return [
|
|
46
|
+
['Enter', 'send code'],
|
|
47
|
+
['Esc', 'back'],
|
|
48
|
+
];
|
|
49
|
+
case 'code':
|
|
50
|
+
return [
|
|
51
|
+
['Enter', 'sign in'],
|
|
52
|
+
['Esc', 'use another email'],
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=sign-in-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sign-in-panel.js","sourceRoot":"","sources":["../../../src/panels/sign-in/sign-in-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { errorMessage } from '@jinion/core/lib/errors';
|
|
3
|
+
import { useApi } from '../../app/api.js';
|
|
4
|
+
/**
|
|
5
|
+
* Signing in to Jinion's own account, which runs in the core. Nothing here says it worked: the app's `jinionUser`
|
|
6
|
+
* field changes, and the app draws itself in place of the sign-in.
|
|
7
|
+
*/
|
|
8
|
+
export function useJinionSignIn() {
|
|
9
|
+
const api = useApi();
|
|
10
|
+
const [step, setStep] = useState({ kind: 'choose' });
|
|
11
|
+
// Set while the browser has a GitHub sign-in, so leaving cancels it and its refusal isn't shown as a problem.
|
|
12
|
+
const github = useRef(undefined);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const stopLink = api.client.on('jinion/sign-in-link', ({ url }) => setStep((now) => (now.kind === 'github' ? { ...now, link: url } : now)));
|
|
15
|
+
return () => {
|
|
16
|
+
stopLink();
|
|
17
|
+
if (github.current === 'waiting')
|
|
18
|
+
api.act(api.request('jinion/sign-in-cancel', {}));
|
|
19
|
+
};
|
|
20
|
+
}, []);
|
|
21
|
+
const withGithub = () => {
|
|
22
|
+
github.current = 'waiting';
|
|
23
|
+
setStep({ kind: 'github' });
|
|
24
|
+
void api.request('jinion/sign-in-github', {}).then(() => {
|
|
25
|
+
github.current = undefined;
|
|
26
|
+
}, (error) => {
|
|
27
|
+
if (github.current !== 'cancelled')
|
|
28
|
+
setStep({ kind: 'choose', problem: errorMessage(error) });
|
|
29
|
+
github.current = undefined;
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const sendCode = (typed) => {
|
|
33
|
+
const email = typed.trim();
|
|
34
|
+
if (!email)
|
|
35
|
+
return;
|
|
36
|
+
setStep({ kind: 'email', email, sending: true });
|
|
37
|
+
void api.request('jinion/send-code', { email }).then(() => setStep({ kind: 'code', email, code: '' }), (error) => setStep({ kind: 'email', email, problem: errorMessage(error) }));
|
|
38
|
+
};
|
|
39
|
+
const signIn = (typed) => {
|
|
40
|
+
if (step.kind !== 'code')
|
|
41
|
+
return;
|
|
42
|
+
const code = typed.trim();
|
|
43
|
+
if (!code)
|
|
44
|
+
return;
|
|
45
|
+
const { email } = step;
|
|
46
|
+
setStep({ kind: 'code', email, code, checking: true });
|
|
47
|
+
void api.request('jinion/sign-in-email', { email, code }).catch((error) => setStep({ kind: 'code', email, code: '', problem: errorMessage(error) }));
|
|
48
|
+
};
|
|
49
|
+
const back = () => {
|
|
50
|
+
if (step.kind === 'code')
|
|
51
|
+
return setStep({ kind: 'email', email: step.email });
|
|
52
|
+
if (step.kind === 'github') {
|
|
53
|
+
github.current = 'cancelled';
|
|
54
|
+
api.act(api.request('jinion/sign-in-cancel', {}));
|
|
55
|
+
}
|
|
56
|
+
setStep({ kind: 'choose' });
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
step,
|
|
60
|
+
withGithub,
|
|
61
|
+
withEmail: () => setStep({ kind: 'email', email: '' }),
|
|
62
|
+
typeEmail: (email) => setStep({ kind: 'email', email }),
|
|
63
|
+
sendCode,
|
|
64
|
+
typeCode: (code) => step.kind === 'code' && setStep({ ...step, code }),
|
|
65
|
+
signIn,
|
|
66
|
+
back,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=use-jinion-sign-in.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-jinion-sign-in.js","sourceRoot":"","sources":["../../../src/panels/sign-in/use-jinion-sign-in.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { ChoiceList, Panel, Text, useChoiceList, useInput, usePanel, useTheme } from '@jinion/tui';
|
|
4
|
+
import { useAtom, useSetAtom } from 'jotai';
|
|
5
|
+
import { statusItemsAtom, statusPreviewAtom } from '../status/items.js';
|
|
6
|
+
import { useStatusData } from '../status/data.js';
|
|
7
|
+
import { DEFAULT_STATUS_LINE, styleOf } from '../status/line.js';
|
|
8
|
+
import { findSegment, SEGMENTS } from '../status/segments/index.js';
|
|
9
|
+
const VISIBLE = 6;
|
|
10
|
+
const NAME_WIDTH = 13;
|
|
11
|
+
export function StatusLinePanel() {
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
const { close } = usePanel();
|
|
14
|
+
const data = useStatusData();
|
|
15
|
+
const [saved, save] = useAtom(statusItemsAtom);
|
|
16
|
+
const preview = useSetAtom(statusPreviewAtom);
|
|
17
|
+
const [order, setOrder] = useState(() => orderOf(saved));
|
|
18
|
+
const [looks, setLooks] = useState(() => looksOf(saved));
|
|
19
|
+
const itemsOf = (checked) => order.filter((id) => checked.includes(id)).map((id) => ({ id, ...looks[id] }));
|
|
20
|
+
const list = useChoiceList({
|
|
21
|
+
keys: order,
|
|
22
|
+
mode: 'multiple',
|
|
23
|
+
initialChecked: saved.map((item) => item.id),
|
|
24
|
+
onCancel: close,
|
|
25
|
+
onSubmit: (checked) => {
|
|
26
|
+
save(itemsOf(checked));
|
|
27
|
+
close();
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const draft = itemsOf(list.checked);
|
|
31
|
+
const draftKey = JSON.stringify(draft);
|
|
32
|
+
const choices = order.map((id) => {
|
|
33
|
+
const segment = findSegment(id);
|
|
34
|
+
const look = looks[id];
|
|
35
|
+
const shown = list.isChecked(id);
|
|
36
|
+
const style = styleOf({ id, ...look });
|
|
37
|
+
const sample = segment.render(data, style);
|
|
38
|
+
return {
|
|
39
|
+
key: id,
|
|
40
|
+
label: (_jsxs(Text, { children: [segment.name.padEnd(NAME_WIDTH), _jsx(Text, { dimColor: !shown, children: sample ?? _jsx(Text, { color: theme.muted, children: "nothing to show yet" }) })] })),
|
|
41
|
+
description: [segment.description, segment.styles?.find((candidate) => candidate.id === style)?.name].filter(Boolean).join(' · '),
|
|
42
|
+
aside: shown ? look.side : undefined,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
useEffect(() => preview(draft), [draftKey]);
|
|
46
|
+
// However the panel closes, the line goes back to what is saved.
|
|
47
|
+
useEffect(() => () => preview(undefined), []);
|
|
48
|
+
useInput((input, key) => {
|
|
49
|
+
const id = list.focus;
|
|
50
|
+
const look = looks[id];
|
|
51
|
+
const styles = findSegment(id)?.styles ?? [];
|
|
52
|
+
const restyle = (next) => setLooks({ ...looks, [id]: { ...look, ...next } });
|
|
53
|
+
if ((key.upArrow || key.downArrow) && key.shift) {
|
|
54
|
+
const index = order.indexOf(id);
|
|
55
|
+
const target = index + (key.upArrow ? -1 : 1);
|
|
56
|
+
if (target < 0 || target >= order.length)
|
|
57
|
+
return;
|
|
58
|
+
const moved = [...order];
|
|
59
|
+
moved[index] = moved[target];
|
|
60
|
+
moved[target] = id;
|
|
61
|
+
return setOrder(moved);
|
|
62
|
+
}
|
|
63
|
+
if (key.tab)
|
|
64
|
+
return restyle({ side: look.side === 'left' ? 'right' : 'left' });
|
|
65
|
+
if ((key.leftArrow || key.rightArrow) && styles.length > 1) {
|
|
66
|
+
const index = styles.findIndex((style) => style.id === styleOf({ id, ...look }));
|
|
67
|
+
return restyle({ style: styles[(index + (key.rightArrow ? 1 : -1) + styles.length) % styles.length].id });
|
|
68
|
+
}
|
|
69
|
+
if (input === 'r') {
|
|
70
|
+
setOrder(orderOf(DEFAULT_STATUS_LINE));
|
|
71
|
+
setLooks(looksOf(DEFAULT_STATUS_LINE));
|
|
72
|
+
for (const segment of SEGMENTS)
|
|
73
|
+
list.setChecked(segment.id, DEFAULT_STATUS_LINE.some((item) => item.id === segment.id));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return (_jsx(Panel, { title: "Status line", subtitle: `${list.checked.length} of ${SEGMENTS.length} shown`, header: _jsx(Text, { color: theme.muted, children: "Checked items show in the status line below, in this order. Changes show as you make them." }), hints: [
|
|
77
|
+
['Space', 'select'],
|
|
78
|
+
['Shift+Up/Down', 'move'],
|
|
79
|
+
['Tab', 'side'],
|
|
80
|
+
['Left/Right', 'style'],
|
|
81
|
+
['r', 'reset'],
|
|
82
|
+
['Enter', 'save'],
|
|
83
|
+
['Esc', 'cancel'],
|
|
84
|
+
], children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE }) }));
|
|
85
|
+
}
|
|
86
|
+
const orderOf = (items) => [
|
|
87
|
+
...items.map((item) => item.id),
|
|
88
|
+
...SEGMENTS.filter((segment) => !items.some((item) => item.id === segment.id)).map((segment) => segment.id),
|
|
89
|
+
];
|
|
90
|
+
const looksOf = (items) => Object.fromEntries(SEGMENTS.map((segment) => {
|
|
91
|
+
const item = items.find((candidate) => candidate.id === segment.id);
|
|
92
|
+
return [segment.id, item ? { side: item.side, style: item.style } : { side: 'left' }];
|
|
93
|
+
}));
|
|
94
|
+
//# sourceMappingURL=statusline.js.map
|