2323 helpBar = lipgloss .NewStyle ().Background (lipgloss .Color ("#2d2d44" )).Foreground (lipgloss .Color ("#888888" )).Padding (0 , 1 )
2424 titleStyle = lipgloss .NewStyle ().Background (lipgloss .Color ("#00d9ff" )).Foreground (lipgloss .Color ("#1a1a2e" )).Bold (true ).Padding (0 , 1 )
2525
26- errorColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#ff5555" ))
27- cyanColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#00d9ff" ))
26+ errorColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#ff5555" ))
27+ cyanColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#00d9ff" ))
2828 greenColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#55ff55" ))
2929 yellowColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#ffaa00" ))
3030 magentaColor = lipgloss .NewStyle ().Foreground (lipgloss .Color ("#ff55ff" ))
@@ -64,12 +64,14 @@ type Model struct {
6464 height int
6565 scrollOffset int
6666 paused bool
67- autoScroll bool // auto-scroll to bottom when new logs arrive
68- selectedIdx int // currently selected log entry index
69- detailMode bool // showing detail view of selected entry
70- reverseOrder bool // show newest logs at top instead of bottom
71- showStreamList bool // show full streams list overlay
72- confirmDelete bool // showing delete confirmation
67+ autoScroll bool
68+ selectedIdx int
69+ detailMode bool
70+ reverseOrder bool
71+ showStreamList bool
72+ confirmDelete bool
73+ splashScreen bool
74+ asciiArt string
7375}
7476
7577func New (manager * logtail.Manager , cfg * config.Config ) * Model {
@@ -83,6 +85,8 @@ func New(manager *logtail.Manager, cfg *config.Config) *Model {
8385 selectedStreams [s .Name ] = true
8486 }
8587
88+ asciiArt := loadASCIIArt ()
89+
8690 return & Model {
8791 manager : manager ,
8892 config : cfg ,
@@ -91,14 +95,31 @@ func New(manager *logtail.Manager, cfg *config.Config) *Model {
9195 filteredBuffer : make ([]LogEntry , 0 , 1000 ),
9296 streams : streams ,
9397 selectedStreams : selectedStreams ,
94- autoScroll : true , // auto-scroll enabled by default
98+ autoScroll : true ,
99+ splashScreen : true ,
100+ asciiArt : asciiArt ,
101+ }
102+ }
103+
104+ func loadASCIIArt () string {
105+ data , err := os .ReadFile ("logdump-ascii.txt" )
106+ if err != nil {
107+ return ""
95108 }
109+ return string (data )
96110}
97111
98112func (m * Model ) Init () tea.Cmd {
113+ if m .splashScreen {
114+ return tea .Tick (3 * time .Second , func (t time.Time ) tea.Msg {
115+ return splashTimeoutMsg (t )
116+ })
117+ }
99118 return m .tick ()
100119}
101120
121+ type splashTimeoutMsg time.Time
122+
102123func (m * Model ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
103124 switch msg := msg .(type ) {
104125 case tea.WindowSizeMsg :
@@ -108,6 +129,11 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
108129 m .viewport .Height = msg .Height - 8
109130 m .viewport .SetContent (m .renderTable ())
110131
132+ case splashTimeoutMsg :
133+ m .splashScreen = false
134+ m .viewport .SetContent (m .renderTable ())
135+ return m , m .tick ()
136+
111137 case tea.KeyMsg :
112138 // Handle search mode input FIRST - capture all typeable characters
113139 if m .searchMode {
@@ -277,6 +303,10 @@ func (m *Model) View() string {
277303 return "Initializing..."
278304 }
279305
306+ if m .splashScreen {
307+ return m .renderSplashScreen ()
308+ }
309+
280310 if m .confirmDelete {
281311 return m .renderDeleteConfirm ()
282312 }
@@ -300,6 +330,48 @@ func (m *Model) View() string {
300330 )
301331}
302332
333+ func (m * Model ) renderSplashScreen () string {
334+ lines := strings .Split (m .asciiArt , "\n " )
335+
336+ var maxWidth int
337+ for _ , line := range lines {
338+ if len (line ) > maxWidth {
339+ maxWidth = len (line )
340+ }
341+ }
342+
343+ paddingTop := (m .height - len (lines )) / 2
344+ sidePadding := (m .width - maxWidth ) / 2
345+
346+ var content strings.Builder
347+ for i := 0 ; i < paddingTop ; i ++ {
348+ content .WriteString ("\n " )
349+ }
350+
351+ for _ , line := range lines {
352+ spaces := sidePadding
353+ if spaces < 0 {
354+ spaces = 0
355+ }
356+ content .WriteString (strings .Repeat (" " , spaces ))
357+ content .WriteString (cyanColor .Render (line ))
358+ content .WriteString ("\n " )
359+ }
360+
361+ helpMsg := grayColor .Render ("Press any key to continue..." )
362+ helpPadding := (m .width - lipgloss .Width (helpMsg )) / 2
363+ if helpPadding < 0 {
364+ helpPadding = 0
365+ }
366+
367+ content .WriteString (strings .Repeat ("\n " , paddingTop - 2 ))
368+ content .WriteString (strings .Repeat (" " , helpPadding ))
369+ content .WriteString (helpMsg )
370+ content .WriteString ("\n " )
371+
372+ return lipgloss .NewStyle ().Height (m .height ).Width (m .width ).Render (content .String ())
373+ }
374+
303375func (m * Model ) renderStreamList () string {
304376 title := titleStyle .Render (" STREAMS " )
305377 header := headerBg .Width (m .width ).Render (title + strings .Repeat (" " , max (0 , m .width - lipgloss .Width (title ))))
0 commit comments