ui

package
v0.0.0-...-c0604f6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ColorBackground = lipgloss.Color("235")
	ColorDarkBg     = lipgloss.Color("233")
	ColorPanelBg    = lipgloss.Color("234")
	ColorSand       = lipgloss.Color("180")
	ColorDim        = lipgloss.Color("243")
	ColorDimmer     = lipgloss.Color("239")
	ColorBorder     = lipgloss.Color("94")
	ColorHighlight  = lipgloss.Color("179")
	ColorAmber      = lipgloss.Color("172")
	ColorTitle      = lipgloss.Color("180")
	ColorCommand    = lipgloss.Color("179")
	ColorDesc       = lipgloss.Color("243")
	ColorAccent     = lipgloss.Color("137")
	ColorGreen      = lipgloss.Color("108")
	ColorTyping     = lipgloss.Color("109")
	ColorMention    = lipgloss.Color("179") // gold highlight for @mentions

	// 12 muted cantina tones for nicknames
	NickColors = []color.Color{
		lipgloss.Color("174"),
		lipgloss.Color("109"),
		lipgloss.Color("137"),
		lipgloss.Color("138"),
		lipgloss.Color("108"),
		lipgloss.Color("179"),
		lipgloss.Color("140"),
		lipgloss.Color("67"),
		lipgloss.Color("131"),
		lipgloss.Color("144"),
		lipgloss.Color("136"),
		lipgloss.Color("97"),
	}
)

Cantina palette — ANSI 256 colors.

View Source
var (
	TopBarBorderStyle = lipgloss.NewStyle().
						Border(lipgloss.Border{Bottom: "─"}, false, false, true, false).
						BorderForeground(ColorBorder)

	BottomBarStyle = lipgloss.NewStyle().
					Foreground(ColorDim).
					Border(lipgloss.Border{Top: "─"}, true, false, false, false).
					BorderForeground(ColorBorder).
					Padding(0, 1)

	ChatBorderStyle = lipgloss.NewStyle().
					Border(lipgloss.RoundedBorder()).
					BorderForeground(ColorBorder).
					Foreground(ColorSand)

	// Left sidebar: border on right side
	LeftSidebarStyle = lipgloss.NewStyle().
						Border(lipgloss.NormalBorder(), false, true, false, false).
						BorderForeground(ColorBorder).
						Foreground(ColorSand).
						PaddingTop(1).
						PaddingLeft(1).
						PaddingRight(1)

	// Right sidebar: border on left side
	RightSidebarStyle = lipgloss.NewStyle().
						Border(lipgloss.NormalBorder(), false, false, false, true).
						BorderForeground(ColorBorder).
						Foreground(ColorSand).
						PaddingTop(1).
						PaddingLeft(1).
						PaddingRight(1)

	SystemMsgStyle = lipgloss.NewStyle().
					Foreground(ColorDim).
					Italic(true)

	InputStyle = lipgloss.NewStyle().
				Foreground(ColorSand)

	// Splash screen styles
	SplashBorderStyle = lipgloss.NewStyle().
						Border(lipgloss.RoundedBorder()).
						BorderForeground(ColorBorder).
						Foreground(ColorSand).
						Padding(1, 3)

	SplashTitleStyle = lipgloss.NewStyle().
						Foreground(ColorTitle).
						Bold(true)

	SplashSubtitleStyle = lipgloss.NewStyle().
						Foreground(ColorDim)

	SplashKeyStyle = lipgloss.NewStyle().
					Foreground(ColorHighlight).
					Bold(true)

	SplashDescStyle = lipgloss.NewStyle().
					Foreground(ColorDesc)

	SplashCategoryStyle = lipgloss.NewStyle().
						Foreground(ColorAccent).
						Bold(true).
						MarginTop(1)

	SplashCommandStyle = lipgloss.NewStyle().
						Foreground(ColorCommand).
						Bold(true)

	// Chat message styles
	MsgTimeStyle = lipgloss.NewStyle().
					Foreground(ColorDimmer)

	TypingStyle = lipgloss.NewStyle().
				Foreground(ColorTyping).
				Italic(true)

	// Mention autocomplete popup styles
	MentionPopupStyle = lipgloss.NewStyle().
						Border(lipgloss.RoundedBorder()).
						BorderForeground(ColorBorder).
						Padding(0, 1)

	MentionSelectedStyle = lipgloss.NewStyle().
							Foreground(ColorAmber).
							Bold(true)

	MentionItemStyle = lipgloss.NewStyle().
						Foreground(ColorSand)

	MentionSelfStyle = lipgloss.NewStyle().
						Foreground(ColorAmber).
						Bold(true)

	MentionHighlightStyle = lipgloss.NewStyle().
							Foreground(ColorMention).
							Bold(true)
)

Functions

func GradientText

func GradientText(text string, c1, c2 color.Color, bold bool) string

GradientText renders text with a horizontal color gradient using HCL blending.

func NickBarColor

func NickBarColor(colorIndex int) color.Color

func NickStyle

func NickStyle(colorIndex int) lipgloss.Style

func Overlay

func Overlay(base, modal string, width, height int) string

Overlay composites a modal box on top of a base view, dimming the background. The base view is kept visible but greyed out behind the modal.

func RenderGifBox

func RenderGifBox(msg *chat.Message) string

RenderGifBox renders a GIF message as a bordered box with the current frame.

func RenderPollCard

func RenderPollCard(p *poll.Poll) string

RenderPollCard renders a compact poll card for inline chat display.

func RenderRedditBox

func RenderRedditBox(msg *chat.Message) string

RenderRedditBox renders a shared Reddit post as a styled card in chat.

func TickGifAnimations

func TickGifAnimations(messages []chat.Message) bool

TickGifAnimations advances frames for the most recent N animated GIFs. Returns true if any frame changed (needs redraw).

func WaitForHubMsg

func WaitForHubMsg(ch <-chan session.Msg) tea.Cmd

func WargameHeader

func WargameHeader(wargame string, currentLevel, maxLevel, points, width int) string

WargameHeader renders the mission briefing header for a wargame room.

Types

type AdminConfirmModal

type AdminConfirmModal struct {
	Action  string // "purge", "ban <fp>", etc
	Message string
}

func NewAdminConfirmModal

func NewAdminConfirmModal(action, message string) AdminConfirmModal

func (AdminConfirmModal) Update

func (a AdminConfirmModal) Update(msg tea.Msg) (AdminConfirmModal, tea.Cmd)

func (AdminConfirmModal) View

func (a AdminConfirmModal) View(width, height int) string

type AdminConfirmMsg

type AdminConfirmMsg struct{ Action string }

type App

type App struct {
	// contains filtered or unexported fields
}

func NewApp

func NewApp(sess *session.Session, st *store.Store, h *hub.Hub, onSend func(session.Msg),
	game *sudoku.Game, ps *poll.Store,
	tavernName, tavernDomain, tagline, ownerName, ownerFingerprint, firstRoom string,
	roomTypes map[string]string, gifClient *gif.KlipyClient, ws *wargame.Store,
	ds *dm.Store, rc *reddit.Client) App

func (App) Init

func (a App) Init() tea.Cmd

func (App) Update

func (a App) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (App) View

func (a App) View() tea.View

type BottomBar

type BottomBar struct {
	Width         int
	IsGallery     bool
	IsFeed        bool
	IsRedditFocus bool
	IsTankard     bool
	IsDMMode      bool
	MentionCount  int
	DMUnread      int
}

func NewBottomBar

func NewBottomBar() BottomBar

func (BottomBar) View

func (b BottomBar) View() string

type ChangelogModal

type ChangelogModal struct{}

func NewChangelogModal

func NewChangelogModal() ChangelogModal

func (ChangelogModal) View

func (c ChangelogModal) View(width, height int) string

type ChatView

type ChatView struct {
	OwnerName        string
	OwnerFingerprint string
	// contains filtered or unexported fields
}

func NewChatView

func NewChatView() ChatView

func (*ChatView) AddMessage

func (c *ChatView) AddMessage(msg chat.Message)

func (*ChatView) AddSystemLog

func (c *ChatView) AddSystemLog(text string)

AddSystemLog adds a temporary log message (auto-expires after a few seconds).

func (*ChatView) ClearHighlight

func (c *ChatView) ClearHighlight()

ClearHighlight removes the message highlight.

func (*ChatView) ClearStaleTyping

func (c *ChatView) ClearStaleTyping()

func (ChatView) HasActiveLogs

func (c ChatView) HasActiveLogs() bool

func (ChatView) HasAnimatingGifs

func (c ChatView) HasAnimatingGifs() bool

func (*ChatView) HasInput

func (c *ChatView) HasInput() bool

HasInput returns true if the user has typed something.

func (ChatView) HasTypingUsers

func (c ChatView) HasTypingUsers() bool

func (*ChatView) InputValue

func (c *ChatView) InputValue() string

InputValue returns current input text and clears it.

func (ChatView) IsScrolling

func (c ChatView) IsScrolling() bool

IsScrolling returns true if user scrolled within the last 2 seconds.

func (*ChatView) MentionPopupActive

func (c *ChatView) MentionPopupActive() bool

MentionPopupActive returns true if the autocomplete popup is showing with results.

func (*ChatView) SetHighlight

func (c *ChatView) SetHighlight(idx int)

SetHighlight highlights a specific message index (for reddit focus mode).

func (*ChatView) SetOwnNickname

func (c *ChatView) SetOwnNickname(nick string)

SetOwnNickname sets the current user's nickname for mention highlighting.

func (*ChatView) SetSize

func (c *ChatView) SetSize(width, height int)

func (*ChatView) SetTyping

func (c *ChatView) SetTyping(nick string)

func (*ChatView) Tick

func (c *ChatView) Tick()

func (ChatView) Update

func (c ChatView) Update(msg tea.Msg) (ChatView, tea.Cmd)

func (*ChatView) UpdateMentionPopup

func (c *ChatView) UpdateMentionPopup(onlineNames []string)

UpdateMentionPopup refreshes the autocomplete popup state. onlineNames is the list of users currently in the room.

func (ChatView) View

func (c ChatView) View() string

type CloseModalMsg

type CloseModalMsg struct{}

CloseModalMsg signals modal should close.

type DMBackToInboxMsg

type DMBackToInboxMsg struct{}

type DMInbox

type DMInbox struct {
	// contains filtered or unexported fields
}

func NewDMInbox

func NewDMInbox(convos []dm.Conversation) DMInbox

func (*DMInbox) SetConversations

func (d *DMInbox) SetConversations(convos []dm.Conversation)

func (*DMInbox) SetSize

func (d *DMInbox) SetSize(w, h int)

func (DMInbox) Update

func (d DMInbox) Update(msg tea.Msg) (DMInbox, tea.Cmd)

func (DMInbox) View

func (d DMInbox) View() string

type DMOpenConvoMsg

type DMOpenConvoMsg struct {
	PeerFP   string
	PeerNick string
}

type DMSendMsg

type DMSendMsg struct {
	ToFP   string
	ToNick string
	Text   string
}

type EnterTavernMsg

type EnterTavernMsg struct{}

type ExpandNoteModal

type ExpandNoteModal struct {
	Text     string
	Nickname string
	ColorIdx int
	IsOwn    bool
	NoteID   int
}

func NewExpandNoteModal

func NewExpandNoteModal(text, nick string, colorIdx int, isOwn bool, noteID int) ExpandNoteModal

func (ExpandNoteModal) View

func (e ExpandNoteModal) View(width, height int) string

type FeedView

type FeedView struct {
	// contains filtered or unexported fields
}

func NewFeedView

func NewFeedView() FeedView

func (*FeedView) BackToList

func (f *FeedView) BackToList()

func (*FeedView) CurrentPost

func (f *FeedView) CurrentPost() *reddit.Post

CurrentPost returns the relevant post for the current view. In comment view, returns the post being viewed. In list, returns the selected post.

func (*FeedView) InCommentView

func (f *FeedView) InCommentView() bool

func (*FeedView) SelectedPost

func (f *FeedView) SelectedPost() *reddit.Post

func (*FeedView) SetComments

func (f *FeedView) SetComments(comments []reddit.Comment, post *reddit.Post)

func (*FeedView) SetError

func (f *FeedView) SetError(msg string)

func (*FeedView) SetPosts

func (f *FeedView) SetPosts(posts []reddit.Post)

func (*FeedView) SetSize

func (f *FeedView) SetSize(width, height int)

func (*FeedView) ShowNotice

func (f *FeedView) ShowNotice(text string)

func (FeedView) Update

func (f FeedView) Update(msg tea.Msg) (FeedView, tea.Cmd)

Update handles input.

func (FeedView) View

func (f FeedView) View() string

View renders the feed panel.

type GalleryDeleteMsg

type GalleryDeleteMsg struct{ NoteID int }

type GalleryExpandMsg

type GalleryExpandMsg struct{ Note GalleryNote }

type GalleryMoveMsg

type GalleryMoveMsg struct{ NoteID, X, Y int }

type GalleryNote

type GalleryNote struct {
	ID          int
	X, Y        int
	Text        string
	Nickname    string
	Fingerprint string
	ColorIndex  int
}

type GalleryView

type GalleryView struct {
	// contains filtered or unexported fields
}

func NewGalleryView

func NewGalleryView(fingerprint string) GalleryView

func (*GalleryView) AddNote

func (g *GalleryView) AddNote(n GalleryNote)

func (*GalleryView) ClearAll

func (g *GalleryView) ClearAll()

func (*GalleryView) LoadNotes

func (g *GalleryView) LoadNotes(rows []store.NoteRow)

func (*GalleryView) MoveNote

func (g *GalleryView) MoveNote(id, x, y int)

func (*GalleryView) RandomPosition

func (g *GalleryView) RandomPosition() (int, int)

func (*GalleryView) RemoveNote

func (g *GalleryView) RemoveNote(id int)

func (*GalleryView) SetScreenOffset

func (g *GalleryView) SetScreenOffset(x, y int)

func (*GalleryView) SetSize

func (g *GalleryView) SetSize(w, h int)

func (GalleryView) Update

func (g GalleryView) Update(msg tea.Msg) (GalleryView, tea.Cmd)

func (GalleryView) View

func (g GalleryView) View() string

type GifFrameDataMsg

type GifFrameDataMsg struct {
	Index  int
	Frames []string
	Delays []int
	Err    error
}

GifFrameDataMsg delivers decoded+rendered frames for a single result.

type GifModal

type GifModal struct {
	// contains filtered or unexported fields
}

func NewGifModal

func NewGifModal(query string, client *gif.KlipyClient) GifModal

func (GifModal) Init

func (g GifModal) Init() tea.Cmd

func (GifModal) Update

func (g GifModal) Update(msg tea.Msg) (GifModal, tea.Cmd)

func (GifModal) View

func (g GifModal) View(width, height int) string

type GifSearchResultMsg

type GifSearchResultMsg struct {
	Results []gif.KlipyResult
	Err     error
}

GifSearchResultMsg delivers search results from the background search.

type GifSendMsg

type GifSendMsg struct {
	Frames []string
	Delays []int
	Title  string
	URL    string
}

GifSendMsg carries the selected GIF data back to the app.

type HelpModal

type HelpModal struct{}

func NewHelpModal

func NewHelpModal() HelpModal

func (HelpModal) View

func (h HelpModal) View(width, height int) string

type HubMsg

type HubMsg session.Msg

type JoinRoomModal

type JoinRoomModal struct {
	// contains filtered or unexported fields
}

func NewJoinRoomModal

func NewJoinRoomModal(rooms []string, counts []int, currentRoom string, roomTypes map[string]string) JoinRoomModal

func (JoinRoomModal) Update

func (j JoinRoomModal) Update(msg tea.Msg) (JoinRoomModal, tea.Cmd)

func (JoinRoomModal) View

func (j JoinRoomModal) View(width, height int) string

type JoinRoomMsg

type JoinRoomMsg struct{ Room string }

JoinRoomMsg carries the selected room name.

type LeaderboardMini

type LeaderboardMini struct {
	Name   string
	Level  int
	Points int
}

type LeaderboardModal

type LeaderboardModal struct {
	// contains filtered or unexported fields
}

func NewLeaderboardModal

func NewLeaderboardModal(entries []wargame.LeaderboardEntry, progress []wargame.Progress, myFingerprint string) LeaderboardModal

func (LeaderboardModal) Update

func (l LeaderboardModal) Update(msg tea.Msg) (LeaderboardModal, tea.Cmd)

func (LeaderboardModal) View

func (l LeaderboardModal) View(width, height int) string

type MentionJumpMsg

type MentionJumpMsg struct{ Room string }

MentionJumpMsg signals the user wants to jump to a mentioned room.

type MentionModal

type MentionModal struct {
	// contains filtered or unexported fields
}

func NewMentionModal

func NewMentionModal(mentions []mention.Mention, contexts [][]chat.Message) MentionModal

func (MentionModal) Current

func (m MentionModal) Current() int

Current returns the index of the currently viewed mention.

func (MentionModal) Update

func (m MentionModal) Update(msg tea.Msg) (MentionModal, tea.Cmd)

func (MentionModal) View

func (m MentionModal) View(width, height int) string

type ModalType

type ModalType int
const (
	ModalNone ModalType = iota
	ModalHelp
	ModalNick
	ModalJoinRoom
	ModalPost
	ModalExpandNote
	ModalAdminConfirm
	ModalMention
	ModalPoll
	ModalPollVote
	ModalChangelog
	ModalGif
	ModalSubmitFlag
	ModalLeaderboard
	ModalWargameRules
)

type NickChangeMsg

type NickChangeMsg struct{ Nick string }

NickChangeMsg carries the new nickname from the modal.

type NickModal

type NickModal struct {
	// contains filtered or unexported fields
}

func NewNickModal

func NewNickModal(currentNick string) NickModal

func (NickModal) Update

func (n NickModal) Update(msg tea.Msg) (NickModal, tea.Cmd)

func (NickModal) View

func (n NickModal) View(width, height int) string

type OnlinePanel

type OnlinePanel struct {
	Users       []string
	Width       int
	Height      int
	Frame       int // for animated online dots
	Tankard     *TankardView
	Leaderboard []LeaderboardMini
}

func NewOnlinePanel

func NewOnlinePanel() OnlinePanel

func (OnlinePanel) View

func (o OnlinePanel) View() string

type PollCreateMsg

type PollCreateMsg struct {
	Title   string
	Options []string
}

PollCreateMsg carries the new poll data from the creation modal.

type PollModal

type PollModal struct {
	// contains filtered or unexported fields
}

func NewPollModal

func NewPollModal() PollModal

func (PollModal) Update

func (p PollModal) Update(msg tea.Msg) (PollModal, tea.Cmd)

func (PollModal) View

func (p PollModal) View(width, height int) string

type PollVoteMsg

type PollVoteMsg struct {
	PollID      int
	OptionIndex int
}

PollVoteMsg signals a vote was cast.

type PollVoteOverlay

type PollVoteOverlay struct {
	// contains filtered or unexported fields
}

func NewPollVoteOverlay

func NewPollVoteOverlay(polls []poll.Poll, fingerprint string) PollVoteOverlay

func (*PollVoteOverlay) SetPolls

func (v *PollVoteOverlay) SetPolls(polls []poll.Poll)

SetPolls updates the polls list (called when a vote broadcast arrives).

func (PollVoteOverlay) Update

func (v PollVoteOverlay) Update(msg tea.Msg) (PollVoteOverlay, tea.Cmd)

func (PollVoteOverlay) View

func (v PollVoteOverlay) View(width, height int) string

type PostModal

type PostModal struct {
	// contains filtered or unexported fields
}

func NewPostModal

func NewPostModal() PostModal

func (PostModal) Update

func (p PostModal) Update(msg tea.Msg) (PostModal, tea.Cmd)

func (PostModal) View

func (p PostModal) View(width, height int) string

type PostNoteMsg

type PostNoteMsg struct{ Text string }

type RoomInfo

type RoomInfo struct {
	Name  string
	Count int
}

type RoomsPanel

type RoomsPanel struct {
	Rooms          []RoomInfo
	CurrentRoom    string
	Width          int
	Height         int
	MentionCounts  map[string]int // room name → unread mention count
	ActivityCounts map[string]int // room name → messages in last 10min
	SSHLinks       []string
	RoomTypes      map[string]string // room name → type
	DMUnread       int               // unread DM count
}

func NewRoomsPanel

func NewRoomsPanel() RoomsPanel

func (RoomsPanel) View

func (r RoomsPanel) View() string

type ShowHelpMsg

type ShowHelpMsg struct{}

type Splash

type Splash struct {
	// contains filtered or unexported fields
}

func NewSplash

func NewSplash(nickname, fingerprint string, flair bool, tavernDomain, tagline string) Splash

func (Splash) Init

func (s Splash) Init() tea.Cmd

func (Splash) Update

func (s Splash) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (Splash) View

func (s Splash) View() tea.View

type SubmitFlagMsg

type SubmitFlagMsg struct {
	Flag string
}

SubmitFlagMsg carries the submitted flag back to the app.

type SubmitModal

type SubmitModal struct {
	// contains filtered or unexported fields
}

func NewSubmitModal

func NewSubmitModal(wargame string, currentLevel, maxLevel int) SubmitModal

func (SubmitModal) Update

func (s SubmitModal) Update(msg tea.Msg) (SubmitModal, tea.Cmd)

func (SubmitModal) View

func (s SubmitModal) View(width, height int) string

type SudokuView

type SudokuView struct {
	// contains filtered or unexported fields
}

func NewSudokuView

func NewSudokuView(game *sudoku.Game, fingerprint, nickname string, colorIndex int) SudokuView

func (*SudokuView) AddMessage

func (s *SudokuView) AddMessage(msg chat.Message)

func (*SudokuView) ChatInput

func (s *SudokuView) ChatInput() string

func (SudokuView) FocusChat

func (s SudokuView) FocusChat() bool

func (SudokuView) HasChatInput

func (s SudokuView) HasChatInput() bool

func (*SudokuView) MarkWrong

func (s *SudokuView) MarkWrong(positions []sudoku.Position)

func (*SudokuView) SetSize

func (s *SudokuView) SetSize(width, height int)

func (*SudokuView) Tick

func (s *SudokuView) Tick()

func (SudokuView) Update

func (s SudokuView) Update(msg tea.Msg) (SudokuView, tea.Cmd)

func (SudokuView) View

func (s SudokuView) View() string

type TankardView

type TankardView struct {
	// contains filtered or unexported fields
}

func NewTankardView

func NewTankardView() TankardView

func (*TankardView) Press

func (t *TankardView) Press() tea.Cmd

Press increments the counter. Blocked while animating (~300ms) which prevents hold-repeat from counting.

func (TankardView) Update

func (t TankardView) Update(msg tea.Msg) (TankardView, tea.Cmd)

func (TankardView) View

func (t TankardView) View() string

type TopBar

type TopBar struct {
	TavernName   string
	Room         string
	OnlineCount  int
	WeeklyCount  int
	AllTimeCount int
	Width        int
}

func (TopBar) View

func (t TopBar) View() string

type WargameRulesModal

type WargameRulesModal struct {
	// contains filtered or unexported fields
}

func NewWargameRulesModal

func NewWargameRulesModal(wargame string, isParticipant bool) WargameRulesModal

func (WargameRulesModal) Update

func (w WargameRulesModal) Update(msg tea.Msg) (WargameRulesModal, tea.Cmd)

func (WargameRulesModal) View

func (w WargameRulesModal) View(width, height int) string

type WargameSignupMsg

type WargameSignupMsg struct{}

WargameSignupMsg signals the user wants to join wargames.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL