Skip to content

Commit d06e101

Browse files
authored
fix: small screen handling across the application, especially log viewing issues (#60)
1 parent c47c747 commit d06e101

7 files changed

Lines changed: 734 additions & 228 deletions

File tree

src/components/Banner.tsx

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React, { useState, useEffect, useRef } from "react";
2-
import { Box, Text } from "ink";
2+
import { Box, Text, useStdout } from "ink";
33
import BigText from "ink-big-text";
44
import Gradient from "ink-gradient";
55
import { isLightMode } from "../utils/theme.js";
6-
import { useViewportHeight } from "../hooks/useViewportHeight.js";
76

87
// Dramatic shades of green shimmer - wide range
98
const DARK_SHIMMER_COLORS = [
@@ -91,18 +90,51 @@ const LIGHT_FRAMES = precomputeFrames(
9190

9291
// Minimum width to show the full BigText banner (simple3d font needs ~80 chars for "RUNLOOP.ai")
9392
const MIN_WIDTH_FOR_BIG_BANNER = 90;
93+
// Minimum height to show the full BigText banner - require generous room (40 lines)
94+
const MIN_HEIGHT_FOR_BIG_BANNER = 40;
9495

9596
// Animation interval in ms
9697
const SHIMMER_INTERVAL = 400;
9798

9899
export const Banner = React.memo(() => {
99100
const [frameIndex, setFrameIndex] = useState(0);
100101
const frames = isLightMode() ? LIGHT_FRAMES : DARK_FRAMES;
101-
const { terminalWidth } = useViewportHeight();
102+
const { stdout } = useStdout();
102103
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
103104

104-
// Determine if we should show compact mode
105-
const isCompact = terminalWidth < MIN_WIDTH_FOR_BIG_BANNER;
105+
// Get raw terminal dimensions, responding to resize events
106+
// Default to conservative values if we can't detect (triggers compact mode)
107+
const getDimensions = React.useCallback(
108+
() => ({
109+
width: stdout?.columns && stdout.columns > 0 ? stdout.columns : 80,
110+
height: stdout?.rows && stdout.rows > 0 ? stdout.rows : 20,
111+
}),
112+
[stdout],
113+
);
114+
115+
const [dimensions, setDimensions] = useState(getDimensions);
116+
117+
useEffect(() => {
118+
// Update immediately on mount and when stdout changes
119+
setDimensions(getDimensions());
120+
121+
if (!stdout) return;
122+
123+
const handleResize = () => {
124+
setDimensions(getDimensions());
125+
};
126+
127+
stdout.on("resize", handleResize);
128+
129+
return () => {
130+
stdout.off("resize", handleResize);
131+
};
132+
}, [stdout, getDimensions]);
133+
134+
// Determine if we should show compact mode (not enough width OR height)
135+
const isCompact =
136+
dimensions.width < MIN_WIDTH_FOR_BIG_BANNER ||
137+
dimensions.height < MIN_HEIGHT_FOR_BIG_BANNER;
106138

107139
useEffect(() => {
108140
const tick = () => {

0 commit comments

Comments
 (0)