package main import ( "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/ssh" "github.com/charmbracelet/wish" wishtea "github.com/charmbracelet/wish/bubbletea" "log" ) type model struct { title string sections []string selected int currentScreen string } func initialModel() model { return model{ title: "tuff SSH stuff", sections: []string{"About", "Projects", "Contact"}, currentScreen: "menu", } } func (m model) Init() tea.Cmd { return nil } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "q", "ctrl+c", "esc": return m, tea.Quit case "up", "k": if m.selected > 0 { m.selected-- fmt.Println("up") } case "down", "j": if m.selected < len(m.sections)-1 { m.selected++ fmt.Println("down") } case "enter": m.currentScreen = m.sections[m.selected] return m, nil case "left", "h": case "right", "l": case "b", "backspace": m.currentScreen = "menu" return m, nil default: fmt.Println("click") } } return m, nil } func (m model) View() string { titleStyle := lipgloss.NewStyle(). Bold(true). Foreground(lipgloss.Color("#E2E8F0")). Background(lipgloss.Color("#0F172A")). Padding(0, 3) sectionStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("#94A3B8")) selectedSectionStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("#8A1D7D")). Bold(true) footerStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("#64748B")) var output string if m.currentScreen == "menu" { output = titleStyle.Render(m.title) + "\n\n" output += "Sections:\n" for i, section := range m.sections { if i == m.selected { output += selectedSectionStyle.Render("- "+section) + "\n" } else { output += sectionStyle.Render("- "+section) + "\n" } } } else { switch m.currentScreen { case "About": output = titleStyle.Render("About Me") + "\n\n" + "Tbh I don't even know anymore. <3" case "Projects": output = titleStyle.Render("Projects") + "\n\n" + "Here are some projects I’ve worked on..." case "Contact": output = titleStyle.Render("Contact") + "\n\n" + "Get in touch with me at djordje@ksan.dev." } output += "\n" + footerStyle.Render("Press b to go back to the menu.") + "\n" } output += "\n" + footerStyle.Render("Press q to quit.") + "\n" return output } func main() { server, _ := wish.NewServer( wish.WithAddress("0.0.0.0:2222"), wish.WithHostKeyPath(".ssh/host_ed25519"), wish.WithMiddleware(wishtea.Middleware(teaHandler)), ) _ = server.ListenAndServe() } func teaHandler(s ssh.Session) (tea.Model, []tea.ProgramOption) { ip := s.RemoteAddr().String() user := s.User() println("New connection:") log.Println("User:", user, "IP:", ip) return initialModel(), []tea.ProgramOption{ tea.WithAltScreen(), } }