gbos 1.1.4 → 1.1.5
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/package.json +1 -1
- package/src/lib/display.js +225 -122
package/package.json
CHANGED
package/src/lib/display.js
CHANGED
|
@@ -2,69 +2,108 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const { PNG } = require('pngjs');
|
|
4
4
|
|
|
5
|
-
// ANSI
|
|
5
|
+
// ANSI escape codes
|
|
6
|
+
const ESC = '\x1b';
|
|
7
|
+
const RESET = `${ESC}[0m`;
|
|
8
|
+
const BOLD = `${ESC}[1m`;
|
|
9
|
+
const DIM = `${ESC}[2m`;
|
|
10
|
+
|
|
11
|
+
// True color ANSI helpers
|
|
12
|
+
const fg = (r, g, b) => `${ESC}[38;2;${r};${g};${b}m`;
|
|
13
|
+
const bg = (r, g, b) => `${ESC}[48;2;${r};${g};${b}m`;
|
|
14
|
+
|
|
15
|
+
// Purple theme RGB values
|
|
16
|
+
const PURPLE = {
|
|
17
|
+
dark: [75, 0, 130], // Deep purple
|
|
18
|
+
medium: [128, 0, 128], // Purple
|
|
19
|
+
light: [147, 112, 219], // Medium purple
|
|
20
|
+
bright: [186, 85, 211], // Medium orchid
|
|
21
|
+
pale: [216, 191, 216], // Thistle
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// 256-color fallback codes
|
|
6
25
|
const colors = {
|
|
7
|
-
reset:
|
|
8
|
-
bold:
|
|
9
|
-
dim:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
purple6: '\x1b[38;5;141m',
|
|
16
|
-
purple7: '\x1b[38;5;183m',
|
|
17
|
-
white: '\x1b[37m',
|
|
18
|
-
gray: '\x1b[90m',
|
|
19
|
-
green: '\x1b[32m',
|
|
20
|
-
yellow: '\x1b[33m',
|
|
21
|
-
red: '\x1b[31m',
|
|
26
|
+
reset: RESET,
|
|
27
|
+
bold: BOLD,
|
|
28
|
+
dim: DIM,
|
|
29
|
+
purple4: `${ESC}[38;5;93m`,
|
|
30
|
+
purple5: `${ESC}[38;5;99m`,
|
|
31
|
+
purple6: `${ESC}[38;5;141m`,
|
|
32
|
+
purple7: `${ESC}[38;5;183m`,
|
|
33
|
+
white: `${ESC}[37m`,
|
|
22
34
|
};
|
|
23
35
|
|
|
24
|
-
//
|
|
25
|
-
const
|
|
36
|
+
// Unicode half-block characters
|
|
37
|
+
const UPPER_HALF = '▀';
|
|
38
|
+
const LOWER_HALF = '▄';
|
|
39
|
+
const FULL_BLOCK = '█';
|
|
26
40
|
|
|
27
41
|
// Get terminal width
|
|
28
42
|
function getTerminalWidth() {
|
|
29
43
|
return process.stdout.columns || 80;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
|
-
//
|
|
33
|
-
function
|
|
46
|
+
// Sample pixel from PNG at given coordinates
|
|
47
|
+
function samplePixel(png, x, y) {
|
|
48
|
+
const clampedX = Math.max(0, Math.min(Math.floor(x), png.width - 1));
|
|
49
|
+
const clampedY = Math.max(0, Math.min(Math.floor(y), png.height - 1));
|
|
50
|
+
const idx = (png.width * clampedY + clampedX) << 2;
|
|
51
|
+
return {
|
|
52
|
+
r: png.data[idx],
|
|
53
|
+
g: png.data[idx + 1],
|
|
54
|
+
b: png.data[idx + 2],
|
|
55
|
+
a: png.data[idx + 3],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check if pixel is transparent or white (background)
|
|
60
|
+
function isBackground(pixel) {
|
|
61
|
+
return pixel.a < 50 || (pixel.r > 240 && pixel.g > 240 && pixel.b > 240);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Convert PNG to true-color pixel art using half-blocks
|
|
65
|
+
// Each character cell represents 2 vertical pixels
|
|
66
|
+
function imageToPixels(imagePath, targetWidth = 24, targetHeight = 12) {
|
|
34
67
|
try {
|
|
35
68
|
const data = fs.readFileSync(imagePath);
|
|
36
69
|
const png = PNG.sync.read(data);
|
|
37
70
|
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const cellHeight = png.height / height;
|
|
71
|
+
// Each row of output = 2 rows of pixels (using half-blocks)
|
|
72
|
+
const pixelRows = targetHeight * 2;
|
|
73
|
+
const cellWidth = png.width / targetWidth;
|
|
74
|
+
const cellHeight = png.height / pixelRows;
|
|
43
75
|
|
|
44
76
|
const lines = [];
|
|
45
77
|
|
|
46
|
-
for (let
|
|
47
|
-
let
|
|
48
|
-
for (let
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
for (let row = 0; row < targetHeight; row++) {
|
|
79
|
+
let line = '';
|
|
80
|
+
for (let col = 0; col < targetWidth; col++) {
|
|
81
|
+
// Sample top and bottom pixels for this cell
|
|
82
|
+
const topY = row * 2 * cellHeight + cellHeight / 2;
|
|
83
|
+
const bottomY = (row * 2 + 1) * cellHeight + cellHeight / 2;
|
|
84
|
+
const x = col * cellWidth + cellWidth / 2;
|
|
85
|
+
|
|
86
|
+
const topPixel = samplePixel(png, x, topY);
|
|
87
|
+
const bottomPixel = samplePixel(png, x, bottomY);
|
|
88
|
+
|
|
89
|
+
const topBg = isBackground(topPixel);
|
|
90
|
+
const bottomBg = isBackground(bottomPixel);
|
|
91
|
+
|
|
92
|
+
if (topBg && bottomBg) {
|
|
93
|
+
// Both transparent - just a space
|
|
94
|
+
line += ' ';
|
|
95
|
+
} else if (topBg && !bottomBg) {
|
|
96
|
+
// Only bottom has color - use lower half block with fg color
|
|
97
|
+
line += fg(bottomPixel.r, bottomPixel.g, bottomPixel.b) + LOWER_HALF + RESET;
|
|
98
|
+
} else if (!topBg && bottomBg) {
|
|
99
|
+
// Only top has color - use upper half block with fg color
|
|
100
|
+
line += fg(topPixel.r, topPixel.g, topPixel.b) + UPPER_HALF + RESET;
|
|
101
|
+
} else {
|
|
102
|
+
// Both have color - use upper half with fg=top, bg=bottom
|
|
103
|
+
line += fg(topPixel.r, topPixel.g, topPixel.b) + bg(bottomPixel.r, bottomPixel.g, bottomPixel.b) + UPPER_HALF + RESET;
|
|
61
104
|
}
|
|
62
|
-
|
|
63
|
-
const brightness = (r + g + b) / 3;
|
|
64
|
-
const charIndex = Math.floor((1 - brightness / 255) * (ASCII_CHARS.length - 1));
|
|
65
|
-
row += ASCII_CHARS[Math.max(0, Math.min(charIndex, ASCII_CHARS.length - 1))];
|
|
66
105
|
}
|
|
67
|
-
lines.push(
|
|
106
|
+
lines.push(line);
|
|
68
107
|
}
|
|
69
108
|
|
|
70
109
|
return lines;
|
|
@@ -73,52 +112,121 @@ function imageToAscii(imagePath, width = 20) {
|
|
|
73
112
|
}
|
|
74
113
|
}
|
|
75
114
|
|
|
76
|
-
//
|
|
115
|
+
// "gbos.io" pixel art (8 rows tall to match logo height)
|
|
116
|
+
// Each character is approximately 5 wide, total ~35 wide
|
|
117
|
+
function getGbosTextPixels() {
|
|
118
|
+
// 8-row pixel art for "gbos.io"
|
|
119
|
+
// Using purple gradient colors
|
|
120
|
+
const p1 = PURPLE.dark;
|
|
121
|
+
const p2 = PURPLE.medium;
|
|
122
|
+
const p3 = PURPLE.light;
|
|
123
|
+
const p4 = PURPLE.bright;
|
|
124
|
+
|
|
125
|
+
// Pixel art bitmap for "gbos.io" - 8 rows, each row is pairs of pixels
|
|
126
|
+
// 0 = transparent, 1-4 = purple shades
|
|
127
|
+
const bitmap = [
|
|
128
|
+
' 222 2222 222 2222 22 222 ',
|
|
129
|
+
' 2 2 2 2 2 2 2 2 2 2 2 ',
|
|
130
|
+
' 2 2 2 2 2 2 2 2 2 ',
|
|
131
|
+
' 2 222 2222 2 2 222 2 2 2 ',
|
|
132
|
+
' 2 2 2 2 2 2 2 2 2 2 ',
|
|
133
|
+
' 2 2 2 2 2 2 2 22 2 2 2 2 ',
|
|
134
|
+
' 222 2222 222 2222 22 22 222 ',
|
|
135
|
+
' ',
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
const lines = [];
|
|
139
|
+
const colorMap = {
|
|
140
|
+
' ': null,
|
|
141
|
+
'1': p1,
|
|
142
|
+
'2': p2,
|
|
143
|
+
'3': p3,
|
|
144
|
+
'4': p4,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Process 2 bitmap rows at a time into 1 output row (half-block technique)
|
|
148
|
+
for (let row = 0; row < bitmap.length; row += 2) {
|
|
149
|
+
let line = '';
|
|
150
|
+
const topRow = bitmap[row] || '';
|
|
151
|
+
const bottomRow = bitmap[row + 1] || '';
|
|
152
|
+
const width = Math.max(topRow.length, bottomRow.length);
|
|
153
|
+
|
|
154
|
+
for (let col = 0; col < width; col++) {
|
|
155
|
+
const topChar = topRow[col] || ' ';
|
|
156
|
+
const bottomChar = bottomRow[col] || ' ';
|
|
157
|
+
const topColor = colorMap[topChar];
|
|
158
|
+
const bottomColor = colorMap[bottomChar];
|
|
159
|
+
|
|
160
|
+
if (!topColor && !bottomColor) {
|
|
161
|
+
line += ' ';
|
|
162
|
+
} else if (!topColor && bottomColor) {
|
|
163
|
+
line += fg(bottomColor[0], bottomColor[1], bottomColor[2]) + LOWER_HALF + RESET;
|
|
164
|
+
} else if (topColor && !bottomColor) {
|
|
165
|
+
line += fg(topColor[0], topColor[1], topColor[2]) + UPPER_HALF + RESET;
|
|
166
|
+
} else {
|
|
167
|
+
line += fg(topColor[0], topColor[1], topColor[2]) + bg(bottomColor[0], bottomColor[1], bottomColor[2]) + UPPER_HALF + RESET;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
lines.push(line);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return lines;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Fallback compact logo
|
|
77
177
|
const COMPACT_LOGO = [
|
|
78
|
-
`${
|
|
79
|
-
`${
|
|
80
|
-
`${
|
|
81
|
-
`${
|
|
82
|
-
`${
|
|
178
|
+
`${fg(...PURPLE.medium)} ▄▀▀▀▄▄${RESET}`,
|
|
179
|
+
`${fg(...PURPLE.medium)}▄▀${fg(...PURPLE.bright)}●${fg(...PURPLE.medium)} ▀▄${RESET}`,
|
|
180
|
+
`${fg(...PURPLE.light)}█ █${RESET}`,
|
|
181
|
+
`${fg(...PURPLE.light)} ▀▄ ▄▀${RESET}`,
|
|
182
|
+
`${fg(...PURPLE.bright)} ▀▀▀▀${RESET}`,
|
|
83
183
|
];
|
|
84
184
|
|
|
185
|
+
// Combine logo and text side by side
|
|
186
|
+
function combineLogoAndText(logoLines, textLines) {
|
|
187
|
+
const combined = [];
|
|
188
|
+
const maxLines = Math.max(logoLines.length, textLines.length);
|
|
189
|
+
const logoStart = Math.floor((maxLines - logoLines.length) / 2);
|
|
190
|
+
const textStart = Math.floor((maxLines - textLines.length) / 2);
|
|
191
|
+
|
|
192
|
+
for (let i = 0; i < maxLines; i++) {
|
|
193
|
+
const logo = logoLines[i - logoStart] || '';
|
|
194
|
+
const text = textLines[i - textStart] || '';
|
|
195
|
+
combined.push(logo + ' ' + text);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return combined;
|
|
199
|
+
}
|
|
200
|
+
|
|
85
201
|
// Display logo with connection details
|
|
86
202
|
function displayLogoWithDetails(details = null) {
|
|
87
|
-
const logoPath = path.join(__dirname, '../../images/logo.png');
|
|
203
|
+
const logoPath = path.join(__dirname, '../../images/logo.png');
|
|
88
204
|
const termWidth = getTerminalWidth();
|
|
89
|
-
const logoWidth = 20;
|
|
90
|
-
const rightWidth = termWidth - logoWidth - 8;
|
|
91
|
-
|
|
92
|
-
let asciiLines = imageToAscii(logoPath, logoWidth);
|
|
93
|
-
|
|
94
|
-
// Color all ASCII lines purple and add "gbos.io" text
|
|
95
|
-
if (asciiLines && asciiLines.length > 0) {
|
|
96
|
-
asciiLines = asciiLines.map((line, idx) => {
|
|
97
|
-
const coloredLine = colors.purple3 + line + colors.reset;
|
|
98
|
-
const midPoint = Math.floor(asciiLines.length / 2);
|
|
99
|
-
if (idx === midPoint) {
|
|
100
|
-
return coloredLine + ` ${colors.purple5}${colors.bold}gbos.io${colors.reset}`;
|
|
101
|
-
}
|
|
102
|
-
return coloredLine;
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
205
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
206
|
+
// Render logo at ~24 chars wide, 6 rows tall (12 pixel rows with half-blocks)
|
|
207
|
+
let logoLines = imageToPixels(logoPath, 24, 6);
|
|
208
|
+
if (!logoLines) logoLines = COMPACT_LOGO;
|
|
209
|
+
|
|
210
|
+
// Get pixel art text
|
|
211
|
+
const textLines = getGbosTextPixels();
|
|
212
|
+
|
|
213
|
+
// Combine logo and text
|
|
214
|
+
const leftSide = combineLogoAndText(logoLines, textLines);
|
|
215
|
+
const leftWidth = 70; // Account for escape codes
|
|
109
216
|
|
|
110
217
|
// Build right side (details box)
|
|
218
|
+
const rightWidth = Math.max(30, termWidth - 75);
|
|
111
219
|
const rightLines = [];
|
|
112
220
|
|
|
113
221
|
if (details) {
|
|
114
|
-
rightLines.push(`${colors.purple4}┌${'─'.repeat(rightWidth - 2)}┐${
|
|
115
|
-
rightLines.push(`${colors.purple4}│${
|
|
116
|
-
rightLines.push(`${colors.purple4}├${'─'.repeat(rightWidth - 2)}┤${
|
|
222
|
+
rightLines.push(`${colors.purple4}┌${'─'.repeat(rightWidth - 2)}┐${RESET}`);
|
|
223
|
+
rightLines.push(`${colors.purple4}│${RESET} ${BOLD}${colors.purple5}Connected${RESET}${' '.repeat(rightWidth - 12)}${colors.purple4}│${RESET}`);
|
|
224
|
+
rightLines.push(`${colors.purple4}├${'─'.repeat(rightWidth - 2)}┤${RESET}`);
|
|
117
225
|
|
|
118
226
|
const addField = (label, value, valueColor = colors.white) => {
|
|
119
227
|
const val = (value || 'N/A').toString().substring(0, rightWidth - label.length - 6);
|
|
120
228
|
const padding = ' '.repeat(Math.max(0, rightWidth - label.length - val.length - 5));
|
|
121
|
-
rightLines.push(`${colors.purple4}│${
|
|
229
|
+
rightLines.push(`${colors.purple4}│${RESET} ${colors.purple7}${label}${RESET} ${valueColor}${val}${RESET}${padding}${colors.purple4}│${RESET}`);
|
|
122
230
|
};
|
|
123
231
|
|
|
124
232
|
addField('Account:', details.accountName, colors.white);
|
|
@@ -129,20 +237,22 @@ function displayLogoWithDetails(details = null) {
|
|
|
129
237
|
addField('Conn:', details.connectionId.substring(0, 18) + '...', colors.dim);
|
|
130
238
|
}
|
|
131
239
|
|
|
132
|
-
rightLines.push(`${colors.purple4}└${'─'.repeat(rightWidth - 2)}┘${
|
|
240
|
+
rightLines.push(`${colors.purple4}└${'─'.repeat(rightWidth - 2)}┘${RESET}`);
|
|
133
241
|
}
|
|
134
242
|
|
|
135
243
|
// Print side by side
|
|
136
244
|
console.log('');
|
|
137
|
-
const maxLines = Math.max(
|
|
138
|
-
const
|
|
139
|
-
const
|
|
245
|
+
const maxLines = Math.max(leftSide.length, rightLines.length);
|
|
246
|
+
const leftStart = Math.floor((maxLines - leftSide.length) / 2);
|
|
247
|
+
const rightStart = Math.floor((maxLines - rightLines.length) / 2);
|
|
140
248
|
|
|
141
249
|
for (let i = 0; i < maxLines; i++) {
|
|
142
|
-
const left =
|
|
143
|
-
const right = rightLines[i -
|
|
144
|
-
|
|
145
|
-
|
|
250
|
+
const left = leftSide[i - leftStart] || '';
|
|
251
|
+
const right = rightLines[i - rightStart] || '';
|
|
252
|
+
// Pad left side accounting for ANSI codes (rough estimate)
|
|
253
|
+
const visibleLen = left.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
254
|
+
const padding = ' '.repeat(Math.max(0, leftWidth - visibleLen));
|
|
255
|
+
console.log(` ${left}${padding}${right}`);
|
|
146
256
|
}
|
|
147
257
|
console.log('');
|
|
148
258
|
}
|
|
@@ -152,63 +262,56 @@ function displayLogo() {
|
|
|
152
262
|
}
|
|
153
263
|
|
|
154
264
|
function displayAuthSuccess(data) {
|
|
265
|
+
const logoPath = path.join(__dirname, '../../images/logo.png');
|
|
155
266
|
const termWidth = getTerminalWidth();
|
|
156
|
-
const logoWidth = 20;
|
|
157
|
-
const rightWidth = termWidth - logoWidth - 8;
|
|
158
267
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// Color all ASCII lines purple and add "gbos.io" text
|
|
163
|
-
if (asciiLines && asciiLines.length > 0) {
|
|
164
|
-
const midPoint = Math.floor(asciiLines.length / 2);
|
|
165
|
-
asciiLines = asciiLines.map((line, idx) => {
|
|
166
|
-
const coloredLine = colors.purple3 + line + colors.reset;
|
|
167
|
-
if (idx === midPoint) {
|
|
168
|
-
return coloredLine + ` ${colors.purple5}${colors.bold}gbos.io${colors.reset}`;
|
|
169
|
-
}
|
|
170
|
-
return coloredLine;
|
|
171
|
-
});
|
|
172
|
-
}
|
|
268
|
+
let logoLines = imageToPixels(logoPath, 24, 6);
|
|
269
|
+
if (!logoLines) logoLines = COMPACT_LOGO;
|
|
173
270
|
|
|
174
|
-
|
|
271
|
+
const textLines = getGbosTextPixels();
|
|
272
|
+
const leftSide = combineLogoAndText(logoLines, textLines);
|
|
273
|
+
const leftWidth = 70;
|
|
175
274
|
|
|
275
|
+
const rightWidth = Math.max(30, termWidth - 75);
|
|
176
276
|
const rightLines = [];
|
|
177
|
-
|
|
178
|
-
rightLines.push(`${colors.purple4}
|
|
179
|
-
rightLines.push(`${colors.purple4}
|
|
277
|
+
|
|
278
|
+
rightLines.push(`${colors.purple4}┌${'─'.repeat(rightWidth - 2)}┐${RESET}`);
|
|
279
|
+
rightLines.push(`${colors.purple4}│${RESET} ${BOLD}${colors.purple5}✓ Authenticated${RESET}${' '.repeat(rightWidth - 18)}${colors.purple4}│${RESET}`);
|
|
280
|
+
rightLines.push(`${colors.purple4}├${'─'.repeat(rightWidth - 2)}┤${RESET}`);
|
|
180
281
|
|
|
181
282
|
const addField = (label, value) => {
|
|
182
283
|
const val = (value || 'N/A').toString().substring(0, rightWidth - label.length - 6);
|
|
183
284
|
const padding = ' '.repeat(Math.max(0, rightWidth - label.length - val.length - 5));
|
|
184
|
-
rightLines.push(`${colors.purple4}│${
|
|
285
|
+
rightLines.push(`${colors.purple4}│${RESET} ${colors.purple7}${label}${RESET} ${colors.white}${val}${RESET}${padding}${colors.purple4}│${RESET}`);
|
|
185
286
|
};
|
|
186
287
|
|
|
187
288
|
addField('User:', data.userId);
|
|
188
289
|
addField('Account:', data.accountId);
|
|
189
290
|
addField('Session:', (data.sessionId || '').substring(0, 24) + '...');
|
|
190
291
|
|
|
191
|
-
rightLines.push(`${colors.purple4}└${'─'.repeat(rightWidth - 2)}┘${
|
|
292
|
+
rightLines.push(`${colors.purple4}└${'─'.repeat(rightWidth - 2)}┘${RESET}`);
|
|
192
293
|
rightLines.push('');
|
|
193
|
-
rightLines.push(`${colors.purple7}${
|
|
294
|
+
rightLines.push(`${colors.purple7}${DIM}Run "gbos connect" to connect${RESET}`);
|
|
194
295
|
|
|
195
296
|
console.log('');
|
|
196
|
-
const maxLines = Math.max(
|
|
197
|
-
const
|
|
198
|
-
const
|
|
297
|
+
const maxLines = Math.max(leftSide.length, rightLines.length);
|
|
298
|
+
const leftStart = Math.floor((maxLines - leftSide.length) / 2);
|
|
299
|
+
const rightStart = Math.floor((maxLines - rightLines.length) / 2);
|
|
199
300
|
|
|
200
301
|
for (let i = 0; i < maxLines; i++) {
|
|
201
|
-
const left =
|
|
202
|
-
const right = rightLines[i -
|
|
203
|
-
|
|
302
|
+
const left = leftSide[i - leftStart] || '';
|
|
303
|
+
const right = rightLines[i - rightStart] || '';
|
|
304
|
+
const visibleLen = left.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
305
|
+
const padding = ' '.repeat(Math.max(0, leftWidth - visibleLen));
|
|
306
|
+
console.log(` ${left}${padding}${right}`);
|
|
204
307
|
}
|
|
205
308
|
console.log('');
|
|
206
309
|
}
|
|
207
310
|
|
|
208
311
|
function displayConnectSuccess(data) {
|
|
209
312
|
displayLogoWithDetails(data);
|
|
210
|
-
console.log(` ${colors.purple5}✓${
|
|
211
|
-
console.log(` ${
|
|
313
|
+
console.log(` ${colors.purple5}✓${RESET} ${BOLD}${colors.purple6}Ready to work!${RESET}`);
|
|
314
|
+
console.log(` ${DIM}${colors.purple7}Session: ~/.gbos/session.json${RESET}\n`);
|
|
212
315
|
}
|
|
213
316
|
|
|
214
317
|
function displaySessionSummary(data) {
|
|
@@ -216,29 +319,29 @@ function displaySessionSummary(data) {
|
|
|
216
319
|
}
|
|
217
320
|
|
|
218
321
|
function displayMessageBox(title, message, type = 'info') {
|
|
219
|
-
const colorMap = { info: colors.purple4, success: colors.purple5, warning:
|
|
322
|
+
const colorMap = { info: colors.purple4, success: colors.purple5, warning: `${ESC}[33m`, error: `${ESC}[31m` };
|
|
220
323
|
const color = colorMap[type] || colors.purple4;
|
|
221
324
|
const icon = type === 'success' ? '✓' : type === 'warning' ? '⚠' : type === 'error' ? '✗' : 'ℹ';
|
|
222
325
|
const width = Math.min(55, getTerminalWidth() - 4);
|
|
223
326
|
|
|
224
|
-
console.log(`\n${color}┌${'─'.repeat(width)}┐${
|
|
225
|
-
console.log(`${color}│${
|
|
226
|
-
console.log(`${color}├${'─'.repeat(width)}┤${
|
|
327
|
+
console.log(`\n${color}┌${'─'.repeat(width)}┐${RESET}`);
|
|
328
|
+
console.log(`${color}│${RESET} ${icon} ${BOLD}${colors.purple6}${title.substring(0, width - 5).padEnd(width - 4)}${RESET}${color}│${RESET}`);
|
|
329
|
+
console.log(`${color}├${'─'.repeat(width)}┤${RESET}`);
|
|
227
330
|
|
|
228
331
|
const words = message.split(' ');
|
|
229
332
|
let currentLine = '';
|
|
230
333
|
for (const word of words) {
|
|
231
334
|
if ((currentLine + ' ' + word).trim().length > width - 4) {
|
|
232
|
-
console.log(`${color}│${
|
|
335
|
+
console.log(`${color}│${RESET} ${colors.purple7}${currentLine.trim().padEnd(width - 2)}${RESET}${color}│${RESET}`);
|
|
233
336
|
currentLine = word;
|
|
234
337
|
} else {
|
|
235
338
|
currentLine = currentLine ? currentLine + ' ' + word : word;
|
|
236
339
|
}
|
|
237
340
|
}
|
|
238
341
|
if (currentLine) {
|
|
239
|
-
console.log(`${color}│${
|
|
342
|
+
console.log(`${color}│${RESET} ${colors.purple7}${currentLine.trim().padEnd(width - 2)}${RESET}${color}│${RESET}`);
|
|
240
343
|
}
|
|
241
|
-
console.log(`${color}└${'─'.repeat(width)}┘${
|
|
344
|
+
console.log(`${color}└${'─'.repeat(width)}┘${RESET}\n`);
|
|
242
345
|
}
|
|
243
346
|
|
|
244
347
|
module.exports = {
|
|
@@ -249,6 +352,6 @@ module.exports = {
|
|
|
249
352
|
displayAuthSuccess,
|
|
250
353
|
displayConnectSuccess,
|
|
251
354
|
displayMessageBox,
|
|
252
|
-
|
|
355
|
+
imageToPixels,
|
|
253
356
|
getTerminalWidth,
|
|
254
357
|
};
|