Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions src/components/LogoV2/WelcomeV2.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
import * as React from 'react'
import { Box, Text } from 'src/ink.js'

const VERBOO_LOGO = [
' ▄▀▀▀▀▀▀▀▄ ',
'▄▀▀▀▀▀▀▀▀▀▀▀▄',
'▀▀▀ ▀▀▀▀▀ ▀▀▀',
'▀▀▀▀▀▀▀▀▀▀▀▀▀',
'▀▀▀▀▀▄▄▄▀▀▀▀▀',
' ▀▀▀▀▀▀▀▀▀▀▀ ',
'▄▀▀ ▀▀▀▀▀ ▀▀▄',
]

export function WelcomeV2(): React.ReactElement {
const version = MACRO.DISPLAY_VERSION ?? MACRO.VERSION

return (
<Box flexDirection="column" marginY={1} paddingX={1}>
<Box flexDirection="row" gap={1} alignItems="center">
<Text>👻</Text>
<Text bold color="claude">
Verboo Code
</Text>
<Text dimColor>v{version}</Text>
<Box flexDirection="row" gap={2} marginY={1} paddingX={1} alignItems="center">
<Box flexDirection="column">
{VERBOO_LOGO.map((line, index) => (
<Text color="claude" key={index}>
{line}
</Text>
))}
</Box>
<Box paddingLeft={3}>
<Box flexDirection="column">
<Box flexDirection="row" gap={1}>
<Text bold color="claude">
Verboo Code
</Text>
<Text dimColor>v{version}</Text>
</Box>
<Text dimColor>Build, debug, and ship from your terminal.</Text>
</Box>
</Box>
Expand Down
5 changes: 3 additions & 2 deletions src/components/PromptInput/PromptInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2368,9 +2368,10 @@ function getInitialPasteId(messages: Message[]): number {
}
return maxId + 1;
}
function buildPromptBorderText(mode: PromptInputMode): BorderTextOptions {
function buildPromptBorderText(mode: PromptInputMode): BorderTextOptions | undefined {
if (mode !== 'bash') return undefined;
return {
content: mode === 'bash' ? ' shell ' : ' 👻 ',
content: ' shell ',
position: 'top',
align: 'start',
offset: 1
Expand Down
12 changes: 6 additions & 6 deletions src/components/StartupScreen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,20 +194,20 @@ describe('renderStartupScreen', () => {
isLocal: false,
}

test('uses the compact ghost identity in a wide terminal', () => {
test('uses the original mascot identity in a wide terminal', () => {
const output = renderStartupScreen(provider, '0.14.5', '~/project', 120)
const plainOutput = stripAnsi(output)

expect(plainOutput).toContain('👻')
expect(plainOutput).not.toContain('👻')
expect(plainOutput).toContain('Verboo Code')
expect(plainOutput).not.toContain('▄▀▀▀▀▀▀▀▄')
expect(plainOutput).toContain('▄▀▀▀▀▀▀▀▄')
expect(plainOutput).not.toContain('Tokens ilimitados')
expect(output).toContain('\x1b[0m')
expect(output).not.toContain('undefined')
expect(plainOutput.split('\n').every(line => line.length <= 120)).toBe(true)
})

test('keeps the compact identity in a narrow terminal', () => {
test('keeps the original mascot in a narrow terminal when it fits', () => {
const output = stripAnsi(
renderStartupScreen(
{
Expand All @@ -220,8 +220,8 @@ describe('renderStartupScreen', () => {
),
)

expect(output).toContain('👻')
expect(output).not.toContain('▄▀▀▀▀▀▀▀▄')
expect(output).not.toContain('👻')
expect(output).toContain('▄▀▀▀▀▀▀▀▄')
expect(output.split('\n').every(line => line.length <= 70)).toBe(true)
})
})
84 changes: 73 additions & 11 deletions src/components/StartupScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ const ACCENT = [173, 52, 254] as const
const DIMCOL = [120, 100, 140] as const
const STARTUP_DEFAULT_COLUMNS = 80

// Original Verboo mascot. Keep this code-native so it renders consistently in
// terminals without depending on the platform's emoji artwork.
const VERBOO_LOGO = [
' ▄▀▀▀▀▀▀▀▄ ',
'▄▀▀▀▀▀▀▀▀▀▀▀▄',
'▀▀▀ ▀▀▀▀▀ ▀▀▀',
'▀▀▀▀▀▀▀▀▀▀▀▀▀',
'▀▀▀▀▀▄▄▄▀▀▀▀▀',
' ▀▀▀▀▀▀▀▀▀▀▀ ',
'▄▀▀ ▀▀▀▀▀ ▀▀▄',
]

const VERBOO_LOGO_MASK = [
' 011111110 ',
'0111111111110',
'1110111110111',
'1111011101111',
'1111100011111',
' 11111111111 ',
'110 01110 011',
]

const STARTUP_LOGO_MIN_COLUMNS = 48

// ─── Provider detection ───────────────────────────────────────────────────────

function resolveVerbooStartupModel(modelOverride?: string): string {
Expand Down Expand Up @@ -169,21 +193,59 @@ export function renderStartupScreen(
const out: string[] = ['']
const bold = `${ESC}1m`
const PURPLE = rgb(...ACCENT)
const PURPLE_FILL = `${PURPLE}${ESC}48;2;${ACCENT[0]};${ACCENT[1]};${ACCENT[2]}m`
const DIMP = `${DIM}${rgb(...DIMCOL)}`
const STATUS_C = p.isLocal ? rgb(130, 200, 140) : PURPLE
const statusLabel = p.isLocal ? 'local' : 'cloud'
const detailWidth = Math.max(1, columns - 8)
const providerAndModel = p.name === 'Verboo' ? p.model : `${p.name} · ${p.model}`
const model = truncateStartupText(providerAndModel, Math.max(1, detailWidth - statusLabel.length - 4))
const cwd = truncateStartupText(displayCwd, detailWidth)
const hint = truncateStartupText('Type a request, or use /help for commands', detailWidth)
const shownVersion = truncateStartupText(version, Math.max(1, columns - 24))

out.push(` 👻 ${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`)
out.push(` ${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`)
out.push(` ${DIMP}${cwd}${RESET}`)
out.push('')
out.push(` ${DIMP}${hint}${RESET}`)

if (columns < STARTUP_LOGO_MIN_COLUMNS) {
const detailWidth = Math.max(1, columns - 4)
const shownVersion = truncateStartupText(version, Math.max(1, columns - 20))
const model = truncateStartupText(providerAndModel, Math.max(1, detailWidth - statusLabel.length - 4))
const cwd = truncateStartupText(displayCwd, detailWidth)

out.push(` ${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`)
out.push(` ${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`)
out.push(` ${DIMP}${cwd}${RESET}`)
} else {
const maxLogoWidth = Math.max(...VERBOO_LOGO.map(line => line.trimEnd().length))
const logoTextPadding = 2
const rightTextWidth = Math.max(1, columns - 2 - maxLogoWidth - logoTextPadding)
const shownVersion = truncateStartupText(version, Math.max(1, rightTextWidth - 16))
const model = truncateStartupText(providerAndModel, Math.max(1, rightTextWidth - statusLabel.length - 5))
const cwd = truncateStartupText(displayCwd, rightTextWidth)
const hint = truncateStartupText('Type a request, or use /help for commands', rightTextWidth)
const rightColumn = [
'',
`${bold}${PURPLE}Verboo Code${RESET} ${DIMP}v${shownVersion}${RESET}`,
`${STATUS_C}●${RESET} ${DIMP}${model} · ${statusLabel}${RESET}`,
`${DIMP}${cwd}${RESET}`,
'',
`${DIMP}${hint}${RESET}`,
'',
]

for (let i = 0; i < VERBOO_LOGO.length; i++) {
const line = (VERBOO_LOGO[i] ?? '').trimEnd()
const mask = VERBOO_LOGO_MASK[i] ?? ''
let painted = ''

for (let j = 0; j < line.length; j++) {
const character = line[j] ?? ''
const isBlock = character === '▀' || character === '▄'
painted += isBlock && mask[j] === '1'
? `${PURPLE_FILL}${character}${RESET}`
: isBlock
? `${PURPLE}${character}${RESET}`
: character
}

const gap = ' '.repeat(Math.max(0, maxLogoWidth - line.length + logoTextPadding))
out.push(` ${painted}${gap}${rightColumn[i] ?? ''}`)
}
}

out.push('')

return `${out.join('\n')}\n`
Expand Down