package main import ( "strings" tea "github.com/charmbracelet/bubbletea" te "github.com/muesli/termenv" "github.com/charmbracelet/bubbles/textinput" ) type chatModel struct { scroll int chatInput textinput.Model } func doSendMessage(conn *loungeConnection, channel int, text string) tea.Cmd { return func() tea.Msg { loungeChannelSend(conn, channel, text) return 1 } } func getMessageString(channelName string, message loungeMessage) string { timestamp := message.Time[11:16] switch message.Type { case messageMessage, messageNotice: if message.From.Nick == "" { return timestamp + " " + message.Text + "\n" } else { return timestamp + " <" + message.From.Mode + message.From.Nick + "> " + message.Text + "\n" } case messageAction: return timestamp + " " + te.String(message.From.Mode + message.From.Nick + " " + message.Text).Italic().String() + "\n" case messageTopic: return timestamp + " " + te.String(message.From.Mode + message.From.Nick + " changed the topic to: " + message.Text).Italic().String() + "\n" case messageError: return timestamp + " " + te.String(message.Text).Foreground(color(errorColor)).String() + "\n" } return "" } func getMessageCounts(m mainModel) (int, int, int) { maxMessages := m.height - 2 messageCount := maxMessages if messageCount > len(m.conn.Channel.Filtered) { messageCount = len(m.conn.Channel.Filtered) } maxScroll := len(m.conn.Channel.Filtered) - messageCount return maxMessages, messageCount, maxScroll } func chatModelInit() chatModel { input := textinput.NewModel() input.Placeholder = "Enter a chat message" input.CharLimit = 256 input.Focus() return chatModel{0, input} } func (m mainModel) chatInit() tea.Cmd { return nil } func (m mainModel) chatView() string { channel := m.conn.Channel if channel == nil { return "No channel open" } s := te.String(channel.Name).Reverse().String() + " " maxTopicLen := m.width - len(channel.Name) - 1 if maxTopicLen < 3 { s += "\n" } else if len(channel.Topic) <= maxTopicLen { s += highlightText(channel.Topic) + "\n" } else { s += highlightText(channel.Topic[:maxTopicLen-3] + "...") + "\n" } maxMessages, messageCount, maxScroll := getMessageCounts(m) if m.chatModel.scroll > maxScroll { m.chatModel.scroll = maxScroll } for i := 0; i < messageCount; i++ { index := len(channel.Filtered) - messageCount - m.chatModel.scroll + i s += getMessageString(channel.Name, channel.Filtered[index]) } s += strings.Repeat("\n", maxMessages - messageCount) s += m.chatModel.chatInput.View() return s } func (m mainModel) chatUpdate(msg tea.Msg) (tea.Model, tea.Cmd) { var ( cmd tea.Cmd cmds []tea.Cmd ) switch msg := msg.(type) { case tea.KeyMsg: if msg.Type == tea.KeyEnter && m.chatModel.chatInput.Value() != "" { cmd = doSendMessage(m.conn, m.conn.Channel.Id, m.chatModel.chatInput.Value()) cmds = append(cmds, cmd) m.chatModel.chatInput.SetValue("") } _, _, maxScroll := getMessageCounts(m) if m.chatModel.scroll > maxScroll { m.chatModel.scroll = maxScroll } if msg.Type == tea.KeyUp { m.chatModel.scroll += 1 } if msg.Type == tea.KeyDown && m.chatModel.scroll > 0 { m.chatModel.scroll -= 1 } } m.chatModel.chatInput, cmd = m.chatModel.chatInput.Update(msg) cmds = append(cmds, cmd) return m, tea.Batch(cmds...) }