mirror of
https://github.com/Adembc/lazyssh.git
synced 2026-07-14 12:13:34 +02:00
feat(ui): remove splash screen and confirm ssh modal (#23)
This commit is contained in:
@@ -169,7 +169,11 @@ func (t *tui) handleSearchToggle() {
|
||||
|
||||
func (t *tui) handleServerConnect() {
|
||||
if server, ok := t.serverList.GetSelectedServer(); ok {
|
||||
t.showConnectModal(server)
|
||||
|
||||
t.app.Suspend(func() {
|
||||
_ = t.serverService.SSH(server.Alias)
|
||||
})
|
||||
t.refreshServerList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,38 +302,6 @@ func (t *tui) showSearchBar() {
|
||||
t.searchVisible = true
|
||||
}
|
||||
|
||||
func (t *tui) showConnectModal(server domain.Server) {
|
||||
msg := fmt.Sprintf("SSH to %s (%s@%s:%d)\n\nConfirm to start an SSH session .",
|
||||
server.Alias, server.User, server.Host, server.Port)
|
||||
|
||||
modal := tview.NewModal().
|
||||
SetText(msg).
|
||||
AddButtons([]string{"Confirm", "Cancel"}).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonIndex == 0 {
|
||||
// Suspend the TUI while running the external ssh command.
|
||||
t.app.Suspend(func() {
|
||||
err := t.serverService.SSH(server.Alias)
|
||||
if err != nil {
|
||||
// Show a brief status after we resume
|
||||
t.app.QueueUpdateDraw(func() {
|
||||
if strings.Contains(strings.ToLower(err.Error()), "timeout") {
|
||||
t.showStatusTempColor("SSH timeout, returning to list", "#FF6B6B")
|
||||
} else {
|
||||
t.showStatusTempColor("SSH failed: "+err.Error(), "#FF6B6B")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// Refresh to reflect updated last seen and ssh count
|
||||
t.refreshServerList()
|
||||
}
|
||||
t.handleModalClose()
|
||||
})
|
||||
|
||||
t.app.SetRoot(modal, true)
|
||||
}
|
||||
|
||||
func (t *tui) showDeleteConfirmModal(server domain.Server) {
|
||||
msg := fmt.Sprintf("Delete server %s (%s@%s:%d)?\n\nThis action cannot be undone.",
|
||||
server.Alias, server.User, server.Host, server.Port)
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
// Copyright 2025.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
// buildSplash creates a splash screen with a spinner; returns primitive and a stop function
|
||||
func buildSplash(app *tview.Application) (tview.Primitive, func()) {
|
||||
// Brand styling
|
||||
title := "[#FFFFFF::b]lazy[-][#55D7FF::b]ssh[-]"
|
||||
tagline := "[#AAAAAA]Fast server picker TUI • Loading your servers…[-]"
|
||||
spinnerFrames := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
|
||||
|
||||
text := tview.NewTextView().
|
||||
SetDynamicColors(true).
|
||||
SetTextAlign(tview.AlignCenter)
|
||||
text.SetBorder(true).
|
||||
SetTitle(" 🚀 lazyssh ").
|
||||
SetBorderColor(tcell.Color238).
|
||||
SetTitleColor(tcell.Color250)
|
||||
|
||||
// layout to center the card
|
||||
box := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(tview.NewBox(), 0, 1, false).
|
||||
AddItem(text, 9, 0, false).
|
||||
AddItem(tview.NewBox(), 0, 1, false)
|
||||
|
||||
container := tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||
AddItem(tview.NewBox(), 0, 1, false).
|
||||
AddItem(box, 0, 2, false).
|
||||
AddItem(tview.NewBox(), 0, 1, false)
|
||||
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
i := 0
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case <-time.After(90 * time.Millisecond):
|
||||
frame := spinnerFrames[i%len(spinnerFrames)]
|
||||
|
||||
width := 20
|
||||
filled := i % (width + 1)
|
||||
prog := strings.Repeat("█", filled) + strings.Repeat("░", width-filled)
|
||||
|
||||
// rotate tips every ~12 frames
|
||||
i++
|
||||
app.QueueUpdateDraw(func() {
|
||||
text.SetText(
|
||||
"\n" +
|
||||
"[::b]" + title + "[-]\n" +
|
||||
"\n" + frame + " " + tagline + "\n" +
|
||||
"\n[#55D7FF]" + prog,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
stopFunc := func() { close(stop) }
|
||||
return container, stopFunc
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"go.uber.org/zap"
|
||||
|
||||
@@ -65,7 +63,8 @@ func (t *tui) Run() error {
|
||||
}
|
||||
}()
|
||||
t.app.EnableMouse(true)
|
||||
t.initializeTheme().buildComponents().buildLayout().bindEvents().loadInitialData().loadSplashScreen()
|
||||
t.initializeTheme().buildComponents().buildLayout().bindEvents().loadInitialData()
|
||||
t.app.SetRoot(t.root, true)
|
||||
t.logger.Infow("starting TUI application", "version", t.version, "commit", t.commit)
|
||||
if err := t.app.Run(); err != nil {
|
||||
t.logger.Errorw("application run error", "error", err)
|
||||
@@ -141,15 +140,3 @@ func (t *tui) updateListTitle() {
|
||||
t.serverList.SetTitle("Servers — Sort: " + t.sortMode.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tui) loadSplashScreen() *tui {
|
||||
splash, stop := buildSplash(t.app)
|
||||
t.app.SetRoot(splash, true)
|
||||
time.AfterFunc(SplashScreenDuration, func() {
|
||||
stop()
|
||||
t.app.QueueUpdateDraw(func() {
|
||||
t.app.SetRoot(t.root, true)
|
||||
})
|
||||
})
|
||||
return t
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user