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() {
|
func (t *tui) handleServerConnect() {
|
||||||
if server, ok := t.serverList.GetSelectedServer(); ok {
|
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
|
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) {
|
func (t *tui) showDeleteConfirmModal(server domain.Server) {
|
||||||
msg := fmt.Sprintf("Delete server %s (%s@%s:%d)?\n\nThis action cannot be undone.",
|
msg := fmt.Sprintf("Delete server %s (%s@%s:%d)?\n\nThis action cannot be undone.",
|
||||||
server.Alias, server.User, server.Host, server.Port)
|
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
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@@ -65,7 +63,8 @@ func (t *tui) Run() error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
t.app.EnableMouse(true)
|
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)
|
t.logger.Infow("starting TUI application", "version", t.version, "commit", t.commit)
|
||||||
if err := t.app.Run(); err != nil {
|
if err := t.app.Run(); err != nil {
|
||||||
t.logger.Errorw("application run error", "error", err)
|
t.logger.Errorw("application run error", "error", err)
|
||||||
@@ -141,15 +140,3 @@ func (t *tui) updateListTitle() {
|
|||||||
t.serverList.SetTitle("Servers — Sort: " + t.sortMode.String())
|
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