@bojackduy/opencode-learn 1.0.0 → 1.1.0
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/dist/tui.js +761 -561
- package/package.json +1 -1
- package/plugins/learn-tui.tsx +35 -11
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@bojackduy/opencode-learn",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"description": "Pi learn system for OpenCode — Socratic teaching, graded quiz, Obsidian md_log, and visual makers. Port of amosblomqvist/learn (video: How I Use AI to Learn Things) to OpenCode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
package/plugins/learn-tui.tsx
CHANGED
|
@@ -99,8 +99,14 @@ function QuizDialog(props: {
|
|
|
99
99
|
const theme = () => props.api.theme.current
|
|
100
100
|
const syntax = () => syntaxStyle(theme())
|
|
101
101
|
const dims = useTerminalDimensions()
|
|
102
|
-
const popupWidth = () =>
|
|
103
|
-
|
|
102
|
+
const popupWidth = () => {
|
|
103
|
+
const w = dims().width
|
|
104
|
+
return Math.max(62, Math.min(w - 8, Math.floor(w * 0.80), 92))
|
|
105
|
+
}
|
|
106
|
+
const popupHeight = () => {
|
|
107
|
+
const h = dims().height
|
|
108
|
+
return Math.max(14, Math.min(h - 6, Math.floor(h * 0.62), 26))
|
|
109
|
+
}
|
|
104
110
|
const options = () => props.request.options
|
|
105
111
|
const correctSet = new Set(props.request.correctIndices)
|
|
106
112
|
const isMulti = () => !!props.request.multiSelect
|
|
@@ -339,6 +345,14 @@ function QuizDialog(props: {
|
|
|
339
345
|
<text fg={theme().background} bold>{phase() === "feedback" ? (feedback()?.correct ? "✓ CORRECT" : dontKnow() ? "○ I DON'T KNOW" : "✗ INCORRECT") : isMulti() ? "☑ QUIZ · MULTI-SELECT" : "● QUIZ · SINGLE" }</text>
|
|
340
346
|
<text fg={theme().background} dim>learn</text>
|
|
341
347
|
</box>
|
|
348
|
+
{/* Pinned scroll cue — header-anchored, high contrast so user instantly knows explanation is below */}
|
|
349
|
+
<Show when={phase()==="feedback" && (canScrollUp() || canScrollDown())}>
|
|
350
|
+
<box justifyContent="center" height={1} backgroundColor={canScrollDown() ? theme().warning : theme().accent} paddingLeft={1} paddingRight={1}>
|
|
351
|
+
<text fg={theme().background} bold>
|
|
352
|
+
{canScrollUp() && canScrollDown() ? "▲ more above · ▼ more below — d / u to scroll" : canScrollDown() ? "▼ more below — press d to see explanation" : "▲ more above — press u to scroll up"}
|
|
353
|
+
</text>
|
|
354
|
+
</box>
|
|
355
|
+
</Show>
|
|
342
356
|
|
|
343
357
|
<scrollbox ref={(el:any)=> scrollRef = el} flexGrow={1} verticalScrollbarOptions={{ visible: true, trackOptions: { backgroundColor: theme().background, foregroundColor: theme().borderActive } }}>
|
|
344
358
|
{/* Question — use opencode markdown render so ```python blocks get syntax coloring like native messages */}
|
|
@@ -459,14 +473,10 @@ function QuizDialog(props: {
|
|
|
459
473
|
<box height={1} justifyContent="center">
|
|
460
474
|
<text fg={theme().textMuted} wrapMode="wrap">
|
|
461
475
|
{phase() === "feedback"
|
|
462
|
-
? (canScrollUp() && canScrollDown() ?
|
|
463
|
-
: canScrollDown() ? "▼ more below — d to scroll · Enter to continue"
|
|
464
|
-
: canScrollUp() ? "▲ more above — u to scroll · Enter to continue"
|
|
465
|
-
: "↵ Enter / Esc to continue → next probe")
|
|
476
|
+
? (canScrollUp() && canScrollDown() ? <><span style={{fg: theme.warning, bold: true}}>▲ more above · ▼ more below</span><span style={{fg: theme().textMuted}}> — d/u to scroll · Enter to continue</span></> : canScrollDown() ? <><span style={{fg: theme.warning, bold: true}}>▼ more below</span><span style={{fg: theme().textMuted}}> — d to scroll · Enter to continue</span></> : canScrollUp() ? <><span style={{fg: theme.accent, bold: true}}>▲ more above</span><span style={{fg: theme().textMuted}}> — u to scroll · Enter to continue</span></> : "↵ Enter / Esc to continue → next probe")
|
|
466
477
|
: phase() === "classifying" ? "Classifying your note..."
|
|
467
478
|
: focused() === "note" ? "Enter submit note → classify · Tab/Esc back"
|
|
468
|
-
: (canScrollUp() || canScrollDown()) ?
|
|
469
|
-
: "j/k or ↑↓ move · Space toggle · Tab note · Enter submit · Esc cancel"}
|
|
479
|
+
: (canScrollUp() || canScrollDown()) ? <><span style={{fg: theme().textMuted}}>j/k or ↑↓ move · Space toggle · Tab note · Enter submit · Esc cancel</span><span style={{fg: theme.warning, bold: true}}> · d/u scroll</span></> : "j/k or ↑↓ move · Space toggle · Tab note · Enter submit · Esc cancel"}
|
|
470
480
|
</text>
|
|
471
481
|
</box>
|
|
472
482
|
</box>
|
|
@@ -483,8 +493,14 @@ function QuizBatchDialog(props: {
|
|
|
483
493
|
const theme = () => props.api.theme.current
|
|
484
494
|
const syntax = () => syntaxStyle(theme())
|
|
485
495
|
const dims = useTerminalDimensions()
|
|
486
|
-
const popupWidth = () =>
|
|
487
|
-
|
|
496
|
+
const popupWidth = () => {
|
|
497
|
+
const w = dims().width
|
|
498
|
+
return Math.max(64, Math.min(w - 8, Math.floor(w * 0.82), 96))
|
|
499
|
+
}
|
|
500
|
+
const popupHeight = () => {
|
|
501
|
+
const h = dims().height
|
|
502
|
+
return Math.max(14, Math.min(h - 6, Math.floor(h * 0.64), 28))
|
|
503
|
+
}
|
|
488
504
|
const [idx, setIdx] = createSignal(0)
|
|
489
505
|
// Guard: if no quizzes, cancel
|
|
490
506
|
if (!props.request.quizzes || props.request.quizzes.length === 0) {
|
|
@@ -656,6 +672,14 @@ function QuizBatchDialog(props: {
|
|
|
656
672
|
<text fg={theme().background} bold> decks.quiz batch {idx()+1}/{props.request.quizzes.length} {phase()==="feedback"?(feedback()?.correct?"✓":"✗"):""}</text>
|
|
657
673
|
<text fg={theme().background} dim>learn</text>
|
|
658
674
|
</box>
|
|
675
|
+
{/* Pinned scroll cue — header-anchored, high contrast */}
|
|
676
|
+
<Show when={phase()==="feedback" && (canScrollUpBatch() || canScrollDownBatch())}>
|
|
677
|
+
<box justifyContent="center" height={1} backgroundColor={canScrollDownBatch() ? theme().warning : theme().accent} paddingLeft={1} paddingRight={1}>
|
|
678
|
+
<text fg={theme().background} bold>
|
|
679
|
+
{canScrollUpBatch() && canScrollDownBatch() ? "▲ more above · ▼ more below — d / u to scroll" : canScrollDownBatch() ? "▼ more below — press d to see explanation" : "▲ more above — press u to scroll up"}
|
|
680
|
+
</text>
|
|
681
|
+
</box>
|
|
682
|
+
</Show>
|
|
659
683
|
<scrollbox ref={(el:any)=> scrollRefBatch = el} flexGrow={1} verticalScrollbarOptions={{ visible: true, trackOptions: { backgroundColor: theme().background, foregroundColor: theme().borderActive } }}>
|
|
660
684
|
<markdown syntaxStyle={syntax()} content={decodeQuizText(cur().question)} fg={theme().text} bg={theme().backgroundPanel} />
|
|
661
685
|
<Show when={cur().details}><markdown syntaxStyle={syntax()} content={decodeQuizText(cur().details)} fg={theme().textMuted} bg={theme().backgroundPanel} /></Show>
|
|
@@ -687,7 +711,7 @@ function QuizBatchDialog(props: {
|
|
|
687
711
|
</scrollbox>
|
|
688
712
|
<box height={1} justifyContent="center">
|
|
689
713
|
<text fg={theme().textMuted} wrapMode="wrap">
|
|
690
|
-
{phase()==="feedback" ? (canScrollUpBatch() && canScrollDownBatch() ?
|
|
714
|
+
{phase()==="feedback" ? (canScrollUpBatch() && canScrollDownBatch() ? <><span style={{fg: theme.warning, bold: true}}>▲ more above · ▼ more below</span><span style={{fg: theme().textMuted}}> — d/u to scroll · Enter → next ({idx()+1}/{props.request.quizzes.length})</span></> : canScrollDownBatch() ? <><span style={{fg: theme.warning, bold: true}}>▼ more below</span><span style={{fg: theme().textMuted}}> — d to scroll · Enter → next ({idx()+1}/{props.request.quizzes.length})</span></> : canScrollUpBatch() ? <><span style={{fg: theme.accent, bold: true}}>▲ more above</span><span style={{fg: theme().textMuted}}> — u to scroll · Enter → next ({idx()+1}/{props.request.quizzes.length})</span></> : `Enter → next (${idx()+1}/${props.request.quizzes.length})`) : phase()==="classifying" ? "Classifying your note..." : focused()==="note" ? "Enter submit note → classify · Tab/Esc back" : (canScrollUpBatch() || canScrollDownBatch()) ? <><span style={{fg: theme().textMuted}}>j/k or ↑↓ move · Space toggle · Tab note · Enter submit · Esc cancel</span><span style={{fg: theme.warning, bold: true}}> · d/u scroll</span></> : "j/k or ↑↓ move · Space toggle · Tab note · Enter submit · Esc cancel"}
|
|
691
715
|
</text>
|
|
692
716
|
</box>
|
|
693
717
|
</box>
|