aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xA/xA.go181
1 files changed, 175 insertions, 6 deletions
diff --git a/xA/xA.go b/xA/xA.go
index c41a167..0149fde 100644
--- a/xA/xA.go
+++ b/xA/xA.go
@@ -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()