feat: logo spin (#597)
This commit is contained in:
@@ -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 (
|
||||
<Box flexDirection="column" padding={1}>
|
||||
<Text color={colors.welcome.accent}>{asciiLogo}</Text>
|
||||
<AnimatedLogo color={colors.welcome.accent} />
|
||||
<Text> </Text>
|
||||
<Text bold>Login to the Letta Developer Platform</Text>
|
||||
<Text> </Text>
|
||||
<Text dimColor>Opening browser for authorization...</Text>
|
||||
@@ -160,7 +161,8 @@ export function SetupUI({ onComplete }: SetupUIProps) {
|
||||
// Main menu
|
||||
return (
|
||||
<Box flexDirection="column" padding={1}>
|
||||
<Text color={colors.welcome.accent}>{asciiLogo}</Text>
|
||||
<AnimatedLogo color={colors.welcome.accent} />
|
||||
<Text> </Text>
|
||||
<Text bold>Welcome to Letta Code!</Text>
|
||||
<Text> </Text>
|
||||
<Text>Let's get you authenticated:</Text>
|
||||
|
||||
123
src/cli/components/AnimatedLogo.tsx
Normal file
123
src/cli/components/AnimatedLogo.tsx
Normal file
@@ -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
|
||||
<Text key={idx} bold color={color}>
|
||||
{line}
|
||||
</Text>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -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({
|
||||
<Box flexDirection="row" marginTop={1}>
|
||||
{/* Left column: Logo */}
|
||||
<Box flexDirection="column" paddingLeft={1} paddingRight={2}>
|
||||
{logoLines.map((line, idx) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: Logo lines are static and never reorder
|
||||
<Text key={idx} bold color={colors.welcome.accent}>
|
||||
{idx === 0 ? ` ${line}` : line}
|
||||
</Text>
|
||||
))}
|
||||
<AnimatedLogo color={colors.welcome.accent} />
|
||||
</Box>
|
||||
|
||||
{/* Right column: Text info */}
|
||||
|
||||
Reference in New Issue
Block a user