diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2024-11-08 16:16:25 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2024-11-09 17:20:19 +0100 |
commit | 9796c5c24a4ca2ffb901adbbf7268f350cc2fff7 (patch) | |
tree | 559fbcab00d09fd9e5786be4422f007f50af101f /xA | |
parent | 0454e2acdb8eabe836fd1c9e717f1f727647061a (diff) | |
download | xK-9796c5c24a4ca2ffb901adbbf7268f350cc2fff7.tar.gz xK-9796c5c24a4ca2ffb901adbbf7268f350cc2fff7.tar.xz xK-9796c5c24a4ca2ffb901adbbf7268f350cc2fff7.zip |
WIP: xA: more message processing
Diffstat (limited to 'xA')
-rw-r--r-- | xA/xA.go | 181 |
1 files changed, 175 insertions, 6 deletions
@@ -118,9 +118,10 @@ type server struct { type bufferLineItem struct { format fyne.TextStyle // For RichTextStyle.ColorName. - // XXX: Fyne's RichText doesn't support background colours. color fyne.ThemeColorName - text string + // XXX: Fyne's RichText doesn't support background colours. + background fyne.ThemeColorName + text string } type bufferLine struct { @@ -188,6 +189,96 @@ var ( // ----------------------------------------------------------------------------- +func defaultBufferLineItem() bufferLineItem { return bufferLineItem{} } + +func convertItemFormatting( + item RelayItemData, cf *bufferLineItem, inverse *bool) { + switch data := item.Variant.(type) { + case *RelayItemDataReset: + *cf = defaultBufferLineItem() + case *RelayItemDataFlipBold: + cf.format.Bold = !cf.format.Bold + case *RelayItemDataFlipItalic: + cf.format.Italic = !cf.format.Italic + case *RelayItemDataFlipUnderline: + cf.format.Underline = !cf.format.Underline + case *RelayItemDataFlipCrossedOut: + // ¯\_(ツ)_/¯ + case *RelayItemDataFlipInverse: + *inverse = !*inverse + case *RelayItemDataFlipMonospace: + cf.format.Monospace = !cf.format.Monospace + case *RelayItemDataFgColor: + if data.Color < 0 { + cf.color = "" + } else { + cf.color = ircColorName(int(data.Color)) + } + case *RelayItemDataBgColor: + if data.Color < 0 { + cf.background = "" + } else { + cf.background = ircColorName(int(data.Color)) + } + } +} + +func convertItems(items []RelayItemData) []bufferLineItem { + result := []bufferLineItem{} + cf, inverse := defaultBufferLineItem(), false + for _, it := range items { + text, ok := it.Variant.(*RelayItemDataText) + if !ok { + convertItemFormatting(it, &cf, &inverse) + continue + } + + item := cf + item.text = text.Text + if inverse { + item.color, item.background = item.background, item.color + } + result = append(result, item) + } + return result +} + +// ----------------------------------------------------------------------------- + +func bufferPrintLine(lines []bufferLine, index int) { + // TODO(p): Date change. + line := &lines[index] + + // TODO(p): Timestamp. + line.when.Format("\n15:04:05") + + // TODO(p): Rendition. + prefix := "" + + if line.leaked { + // TODO(p): Similar as below, but everything greyed out. + if prefix != "" { + } + for _, item := range line.items { + _ = item + } + } else { + // TODO(p): Render text. + if prefix != "" { + } + for _, item := range line.items { + _ = item + } + } +} + +func bufferPrintSeparator() { + // TODO(p) + wRichText.Segments = append(wRichText.Segments, + &widget.TextSegment{Style: widget.RichTextStyleParagraph}, + &widget.SeparatorSegment{}) +} + func refreshBuffer(b *buffer) { // TODO(p): See xW, rewrite the whole buffer view. } @@ -293,6 +384,81 @@ func relayWriteMessage(conn net.Conn, data RelayCommandData) bool { return true } +func convertBufferLine(m *RelayEventDataBufferLine) bufferLine { + return bufferLine{ + items: convertItems(m.Items), + isUnimportant: m.IsUnimportant, + isHighlight: m.IsHighlight, + rendition: m.Rendition, + when: time.UnixMilli(int64(m.When)), + } +} + +func relayProcessBufferLine(b *buffer, m *RelayEventDataBufferLine) { + line := convertBufferLine(m) + + // Initial sync: skip all other processing, let highlights be. + bc := bufferByName(bufferCurrent) + if bc == nil { + b.lines = append(b.lines, line) + return + } + + // Retained mode is complicated. + display := (!m.IsUnimportant || !bc.hideUnimportant) && + (b.bufferName == bufferCurrent || m.LeakToActive) + toBottom := display // && bufferAtBottom() + visible := display && toBottom // && ... + separate := display && + !visible && bc.newMessages == 0 && bc.newUnimportantMessages == 0 + + b.lines = append(b.lines, line) + if !(visible || m.LeakToActive) || + b.newMessages != 0 || b.newUnimportantMessages != 0 { + if line.isUnimportant || m.LeakToActive { + b.newUnimportantMessages++ + } else { + b.newMessages++ + } + } + + if m.LeakToActive { + leakedLine := line + leakedLine.leaked = true + bc.lines = append(bc.lines, leakedLine) + + if !visible || bc.newMessages != 0 || bc.newUnimportantMessages != 0 { + if line.isUnimportant { + bc.newUnimportantMessages++ + } else { + bc.newMessages++ + } + } + } + + if separate { + // TODO(p) + } + if display { + bufferPrintLine(bc.lines, len(bc.lines)-1) + } + if toBottom { + // TODO(p) + } + + if line.isHighlight || (!visible && !line.isUnimportant && + b.kind == RelayBufferKindPrivateMessage) { + // TODO(p): beep(), probably using https://github.com/ebitengine/oto + + if !visible { + b.highlighted = true + refreshIcon() + } + } + + refreshBufferList() +} + func relayProcessCallbacks( commandSeq uint32, err string, response *RelayResponseData) { if handler, ok := commandCallbacks[commandSeq]; !ok { @@ -338,7 +504,12 @@ func relayProcessMessage(m *RelayEventMessage) { } case *RelayEventDataBufferLine: - // TODO(p): Process all remaining message kinds. + b := bufferByName(data.BufferName) + if b == nil { + return + } + + relayProcessBufferLine(b, data) case *RelayEventDataBufferUpdate: b := bufferByName(data.BufferName) if b == nil { @@ -357,13 +528,11 @@ func relayProcessMessage(m *RelayEventMessage) { case *RelayBufferContextChannel: b.serverName = context.ServerName b.modes = context.Modes - // TODO(p): Convert the items. - b.topic = nil + b.topic = convertItems(context.Topic) case *RelayBufferContextPrivateMessage: b.serverName = context.ServerName } - // TODO: Port over the rest as well. if b.bufferName == bufferCurrent { refreshTopic(b.topic) refreshStatus() |