aboutsummaryrefslogtreecommitdiff
path: root/xA/xA.go
blob: 192265fbafa83857c417c003352c879b38c369ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) 2024, Přemysl Eric Janouch <p@janouch.name>
// SPDX-License-Identifier: 0BSD

package main

import (
	"bufio"
	"context"
	"encoding/binary"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/url"
	"os"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

var (
	debug          = flag.Bool("debug", false, "enable debug output")
	projectName    = "xA"
	projectVersion = "?"
	addressConnect string
)

// -----------------------------------------------------------------------------

func relayReadFrame(r io.Reader) []byte {
	var length uint32
	if err := binary.Read(r, binary.BigEndian, &length); err != nil {
		log.Println("Event receive failed: " + err.Error())
		return nil
	}
	b := make([]byte, length)
	if _, err := io.ReadFull(r, b); err != nil {
		log.Println("Event receive failed: " + err.Error())
		return nil
	}

	if *debug {
		log.Printf("<? %v\n", b)

		var m RelayEventMessage
		if after, ok := m.ConsumeFrom(b); !ok {
			log.Println("Event deserialization failed")
			return nil
		} else if len(after) != 0 {
			log.Println("Event deserialization failed: trailing data")
			return nil
		}

		j, err := m.MarshalJSON()
		if err != nil {
			log.Println("Event marshalling failed: " + err.Error())
			return nil
		}

		log.Printf("<- %s\n", j)
	}
	return b
}

func relayMakeReceiver(ctx context.Context, conn net.Conn) <-chan []byte {
	// The usual event message rarely gets above 1 kilobyte,
	// thus this is set to buffer up at most 1 megabyte or so.
	p := make(chan []byte, 1000)
	r := bufio.NewReaderSize(conn, 65536)
	go func() {
		defer close(p)
		for {
			j := relayReadFrame(r)
			if j == nil {
				return
			}
			select {
			case p <- j:
			case <-ctx.Done():
				return
			}
		}
	}()
	return p
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(flag.CommandLine.Output(),
			"Usage: %s [OPTION...] CONNECT\n\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() < 1 || flag.NArg() > 1 {
		flag.Usage()
		os.Exit(1)
	}

	addressConnect = flag.Arg(0)

	// TODO(p): First, test Fyne's GUI capabilities.

	a := app.New()
	w := a.NewWindow(projectName)

	// TODO(p): There should also be a widget.NewLabel() next to the entry.
	//  - Probably another Border, even though this seems odd.
	var (
		richtext   = widget.NewRichText()
		richscroll = container.NewVScroll(richtext)
		entry      = widget.NewMultiLineEntry()
	)
	w.SetContent(container.NewBorder(nil, entry, nil, nil, richscroll))

	testURL, _ := url.Parse("https://x.com")
	richtext.Segments = []widget.RichTextSegment{
		&widget.ParagraphSegment{Texts: []widget.RichTextSegment{
			&widget.TextSegment{Text: "Test"},
			&widget.HyperlinkSegment{Text: "X", URL: testURL},
			&widget.TextSegment{
				Text:  " is a website, certainly",
				Style: widget.RichTextStyleInline,
			},
		}},
		&widget.TextSegment{Style: widget.RichTextStyleParagraph},
		&widget.SeparatorSegment{},
		&widget.TextSegment{Text: "Paragraph"},
	}
	richtext.Wrapping = fyne.TextWrapWord
	richtext.Refresh()

	w.ShowAndRun()
}