diff --git a/src/auth/setup-ui.tsx b/src/auth/setup-ui.tsx index 79f6e00..cba7d30 100644 --- a/src/auth/setup-ui.tsx +++ b/src/auth/setup-ui.tsx @@ -5,7 +5,7 @@ import { hostname } from "node:os"; import { Box, Text, useApp, useInput } from "ink"; import { useState } from "react"; -import { asciiLogo } from "../cli/components/AsciiArt.ts"; +import { AnimatedLogo } from "../cli/components/AnimatedLogo"; import { colors } from "../cli/components/colors"; import { settingsManager } from "../settings-manager"; import { pollForToken, requestDeviceCode } from "./oauth"; @@ -139,7 +139,8 @@ export function SetupUI({ onComplete }: SetupUIProps) { if (mode === "device-code") { return ( - {asciiLogo} + + Login to the Letta Developer Platform Opening browser for authorization... @@ -160,7 +161,8 @@ export function SetupUI({ onComplete }: SetupUIProps) { // Main menu return ( - {asciiLogo} + + Welcome to Letta Code! Let's get you authenticated: diff --git a/src/cli/components/AnimatedLogo.tsx b/src/cli/components/AnimatedLogo.tsx new file mode 100644 index 0000000..f33370a --- /dev/null +++ b/src/cli/components/AnimatedLogo.tsx @@ -0,0 +1,123 @@ +import { Text } from "ink"; +import { useEffect, useState } from "react"; +import { colors } from "./colors"; + +// Define animation frames - 3D rotation effect with gradient (█ → ▓ → ▒ → ░) +// Each frame is ~10 chars wide, 5 lines tall - matches login dialog asciiLogo size +const logoFrames = [ + // 1. Front view (fully facing) + ` ██████ +██ ██ +██ ██ ██ +██ ██ + ██████ `, + // 2. Just starting to turn right + ` ▓█████ +▓█ ▓█ +▓█ ▓█ ▓█ +▓█ ▓█ + ▓█████ `, + // 3. Slight right turn + ` ▓▓████ +▓▓ ▓▓ +▓▓ ▓▓ ▓▓ +▓▓ ▓▓ + ▓▓████ `, + // 4. More right (gradient deepening) + ` ░▓▓███ +░▓▓ ░▓▓ +░▓▓ ░▓ ░▓▓ +░▓▓ ░▓▓ + ░▓▓███ `, + // 5. Even more right + ` ░░▓▓██ + ░▓▓ ░▓▓ + ░▓▓░▓░▓▓ + ░▓▓ ░▓▓ + ░░▓▓██ `, + // 6. Approaching side + ` ░▓▓█ + ░░▓░░▓ + ░░▓▓░▓ + ░░▓░░▓ + ░▓▓█ `, + // 7. Almost side + ` ░▓▓▓ + ░▓░▓ + ░▓▓▓ + ░▓░▓ + ░▓▓▓ `, + // 8. Side view + ` ▓▓▓▓ + ▓▓▓▓ + ▓▓▓▓ + ▓▓▓▓ + ▓▓▓▓ `, + // 9. Leaving side (mirror of 7) + ` ▓▓▓░ + ▓░▓░ + ▓▓▓░ + ▓░▓░ + ▓▓▓░ `, + // 10. Past side (mirror of 6) + ` █▓▓░ + ▓░░▓░░ + ▓░▓▓░░ + ▓░░▓░░ + █▓▓░ `, + // 11. More past side (mirror of 5) + ` ██▓▓░░ + ▓▓░ ▓▓░ + ▓▓░▓░▓▓░ + ▓▓░ ▓▓░ + ██▓▓░░ `, + // 12. Returning (mirror of 4) + ` ███▓▓░ +▓▓░ ▓▓░ +▓▓░ ▓░ ▓▓░ +▓▓░ ▓▓░ + ███▓▓░ `, + // 13. Almost front (mirror of 3) + ` ████▓▓ +▓▓ ▓▓ +▓▓ ▓▓ ▓▓ +▓▓ ▓▓ + ████▓▓ `, + // 14. Nearly front (mirror of 2) + ` █████▓ +█▓ █▓ +█▓ █▓ █▓ +█▓ █▓ + █████▓ `, +]; + +interface AnimatedLogoProps { + color?: string; +} + +export function AnimatedLogo({ + color = colors.welcome.accent, +}: AnimatedLogoProps) { + const [frame, setFrame] = useState(0); + + useEffect(() => { + const timer = setInterval(() => { + setFrame((prev) => (prev + 1) % logoFrames.length); + }, 100); + + return () => clearInterval(timer); + }, []); + + const logoLines = logoFrames[frame]?.split("\n") ?? []; + + return ( + <> + {logoLines.map((line, idx) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: Logo lines are static and never reorder + + {line} + + ))} + + ); +} diff --git a/src/cli/components/WelcomeScreen.tsx b/src/cli/components/WelcomeScreen.tsx index 9a96cd7..82e9158 100644 --- a/src/cli/components/WelcomeScreen.tsx +++ b/src/cli/components/WelcomeScreen.tsx @@ -8,7 +8,7 @@ import { getModelDisplayName } from "../../agent/model"; import { settingsManager } from "../../settings-manager"; import { getVersion } from "../../version"; import { useTerminalWidth } from "../hooks/useTerminalWidth"; -import { asciiLogo } from "./AsciiArt"; +import { AnimatedLogo } from "./AnimatedLogo"; import { colors } from "./colors"; /** @@ -80,7 +80,6 @@ export function WelcomeScreen({ const cwd = process.cwd(); const version = getVersion(); - const logoLines = asciiLogo.trim().split("\n"); const tildePath = toTildePath(cwd); // Get model display name (pretty name if available, otherwise last part of handle) @@ -117,12 +116,7 @@ export function WelcomeScreen({ {/* Left column: Logo */} - {logoLines.map((line, idx) => ( - // biome-ignore lint/suspicious/noArrayIndexKey: Logo lines are static and never reorder - - {idx === 0 ? ` ${line}` : line} - - ))} + {/* Right column: Text info */}