feat(tui): add ASCII art banner on startup
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// ASCII art banner for Flynn TUI startup
|
||||
|
||||
/**
|
||||
* Flynn ASCII art banner using block characters.
|
||||
* Raw art lines without any color codes — callers apply their own styling.
|
||||
*/
|
||||
export const FLYNN_BANNER = `
|
||||
███████╗██╗ ██╗ ██╗███╗ ██╗███╗ ██╗
|
||||
██╔════╝██║ ╚██╗ ██╔╝████╗ ██║████╗ ██║
|
||||
█████╗ ██║ ╚████╔╝ ██╔██╗ ██║██╔██╗ ██║
|
||||
██╔══╝ ██║ ╚██╔╝ ██║╚██╗██║██║╚██╗██║
|
||||
██║ ███████╗ ██║ ██║ ╚████║██║ ╚████║
|
||||
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝`;
|
||||
|
||||
/**
|
||||
* Returns the banner with ANSI color codes for terminal output.
|
||||
* Uses orange (208) for the art and dim for the box frame.
|
||||
*/
|
||||
export function getColoredBanner(): string {
|
||||
const orange = '\x1b[38;5;208m';
|
||||
const reset = '\x1b[0m';
|
||||
|
||||
return `${orange}${FLYNN_BANNER}${reset}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns plain banner lines for use in Ink/React components.
|
||||
* Each line is returned individually for flexible rendering.
|
||||
*/
|
||||
export function getBannerLines(): string[] {
|
||||
return FLYNN_BANNER.split('\n').filter((line) => line.length > 0);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Box, Text, Static } from 'ink';
|
||||
import type { Message } from '../../../models/types.js';
|
||||
import { getMessageText } from '../../../models/media.js';
|
||||
import { renderMarkdown } from '../markdown.js';
|
||||
import { getBannerLines } from '../banner.js';
|
||||
|
||||
export interface MessageListProps {
|
||||
messages: Message[];
|
||||
@@ -80,7 +81,12 @@ export const MessageList = memo(function MessageList({
|
||||
return (
|
||||
<Box flexDirection="column" flexGrow={1} paddingX={1} overflowY="hidden">
|
||||
{visibleMessages.length === 0 && !streamingContent ? (
|
||||
<Text color="gray">No messages yet. Start typing to chat with Flynn.</Text>
|
||||
<Box flexDirection="column" alignItems="center" justifyContent="center" flexGrow={1}>
|
||||
{getBannerLines().map((line, i) => (
|
||||
<Text key={i} color="#ff8c00">{line}</Text>
|
||||
))}
|
||||
<Text color="gray">{'\n'}Start typing to chat with Flynn.</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<>
|
||||
<Static items={visibleMessages}>
|
||||
|
||||
@@ -13,5 +13,6 @@ export {
|
||||
|
||||
export { renderMarkdown } from './markdown.js';
|
||||
export { parseCommand as parseCommandUtil, getHelpText, resolveModelAlias } from './commands.js';
|
||||
export { FLYNN_BANNER, getColoredBanner, getBannerLines } from './banner.js';
|
||||
|
||||
export { App, StatusBar, MessageList, InputBar } from './components/index.js';
|
||||
|
||||
@@ -10,6 +10,7 @@ import { OllamaClient, LlamaCppClient } from '../../models/index.js';
|
||||
import { createClientFromConfig } from '../../daemon/index.js';
|
||||
import { loginGitHub } from '../../auth/index.js';
|
||||
import type { PairingManager } from '../../channels/pairing.js';
|
||||
import { getColoredBanner } from './banner.js';
|
||||
|
||||
export { parseCommand, type Command };
|
||||
|
||||
@@ -125,7 +126,8 @@ export class MinimalTui {
|
||||
readline.emitKeypressEvents(process.stdin);
|
||||
}
|
||||
|
||||
console.log(`${colors.orange}${colors.bold}Flynn TUI${colors.reset} ${colors.dim}(minimal mode)${colors.reset}`);
|
||||
console.log(getColoredBanner());
|
||||
console.log(`\n${colors.orange}${colors.bold}Flynn TUI${colors.reset} ${colors.dim}(minimal mode)${colors.reset}`);
|
||||
console.log(`${colors.gray}Type /help for commands, /fullscreen for panel mode${colors.reset}\n`);
|
||||
|
||||
await this.promptLoop();
|
||||
|
||||
Reference in New Issue
Block a user