-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogo-screen.tsx
More file actions
121 lines (109 loc) · 3.22 KB
/
logo-screen.tsx
File metadata and controls
121 lines (109 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/** @jsxImportSource @opentui/solid */
import { RGBA, TextAttributes } from "@opentui/core";
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui";
import { For, createMemo, type JSX } from "solid-js";
import { useKeyboard } from "@opentui/solid";
const logo = {
left: [
" ",
"█▀▀█ █▀▀█ █▀▀█ █▀▀▄",
"█__█ █__█ █^^^ █__█",
"▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀~~▀",
],
right: [
" ▄ ",
"█▀▀▀ █▀▀█ █▀▀█ █▀▀█",
"█___ █__█ █__█ █^^^",
"▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀",
],
};
const marks = "_^~";
const shadowMarker = new RegExp(`[${marks}]`);
const tint = (a: RGBA, b: RGBA, amt: number) => {
return RGBA.fromValues(
a.r + (b.r - a.r) * amt,
a.g + (b.g - a.g) * amt,
a.b + (b.b - a.b) * amt,
a.a + (b.a - a.a) * amt,
);
};
const renderLine = (line: string, fg: RGBA, background: RGBA, bold: boolean): JSX.Element[] => {
const shadow = tint(background, fg, 0.25);
const attrs = bold ? TextAttributes.BOLD : undefined;
const elements: JSX.Element[] = [];
let i = 0;
while (i < line.length) {
const rest = line.slice(i);
const markerIndex = rest.search(shadowMarker);
if (markerIndex === -1) {
elements.push(
<text fg={fg} attributes={attrs} selectable={false}>
{rest}
</text>,
);
break;
}
if (markerIndex > 0) {
elements.push(
<text fg={fg} attributes={attrs} selectable={false}>
{rest.slice(0, markerIndex)}
</text>,
);
}
switch (rest[markerIndex]) {
case "_":
elements.push(
<text fg={fg} bg={shadow} attributes={attrs} selectable={false}>
{" "}
</text>,
);
break;
case "^":
elements.push(
<text fg={fg} bg={shadow} attributes={attrs} selectable={false}>
▀
</text>,
);
break;
case "~":
elements.push(
<text fg={shadow} attributes={attrs} selectable={false}>
▀
</text>,
);
break;
}
i += markerIndex + 1;
}
return elements;
};
export function LogoScreen(props: { theme: () => TuiThemeCurrent; onExit: () => void }) {
const theme = createMemo(() => props.theme());
useKeyboard((evt) => {
if (evt.name !== "escape") return;
evt.preventDefault();
evt.stopPropagation();
props.onExit();
});
return (
<box width="100%" height="100%" flexDirection="column" alignItems="center">
<box flexGrow={1} minHeight={0} />
<box flexShrink={0}>
<For each={logo.left}>
{(line, index) => (
<box flexDirection="row" gap={1}>
<box flexDirection="row">
{renderLine(line, theme().textMuted, theme().background, false)}
</box>
<box flexDirection="row">
{renderLine(logo.right[index()] ?? "", theme().text, theme().background, true)}
</box>
</box>
)}
</For>
</box>
<box height={3} minHeight={0} flexShrink={0} />
<box flexGrow={1} minHeight={0} />
</box>
);
}