From e2dc5b6fbb6adf6f379ef0123c214a196211c305 Mon Sep 17 00:00:00 2001 From: citrons Date: Sun, 1 Jun 2025 15:38:17 -0500 Subject: joining channels --- client/channel_window.go | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 client/channel_window.go (limited to 'client/channel_window.go') diff --git a/client/channel_window.go b/client/channel_window.go new file mode 100644 index 0000000..abeaa77 --- /dev/null +++ b/client/channel_window.go @@ -0,0 +1,189 @@ +package main + +import ( + "citrons.xyz/talk/client/buffer" + "citrons.xyz/talk/client/window" + "citrons.xyz/talk/proto" + "citrons.xyz/talk/tui" + "strconv" + "time" +) + +type channelLocation struct { + id string +} + +type channelWindow struct { + location channelLocation + buf buffer.Buffer + input tui.TextInput + watchedUsers map[string]bool + loadingHistory bool +} + +type channelMsg struct { + proto.Object + window *channelWindow +} + +func (cl channelLocation) CreateWindow() window.Window { + if !globalApp.connected { + return nil + } + cw := &channelWindow { + location: cl, watchedUsers: make(map[string]bool), + } + globalApp.cache.Watch(cl.id) + return cw +} + +func (cw *channelWindow) getChannel() *proto.Object { + return globalApp.cache.Get(cw.location.id) +} + +func (cw *channelWindow) watchUser(uid string) { + if !cw.watchedUsers[uid] { + globalApp.cache.Watch(uid) + cw.watchedUsers[uid] = true + } +} + +func (cw *channelWindow) username(uid string) string { + cw.watchUser(uid) + u := globalApp.cache.Get(uid) + if u != nil { + return u.Fields[""] + } + return "..." +} + +func (cw *channelWindow) put(msg proto.Object) { + cw.buf.Add(channelMsg {msg, cw}) +} + +func (cw *channelWindow) Location() window.Location { + return cw.location +} + +func (cw *channelWindow) Kill() { + globalApp.cache.Unwatch(cw.location.id) + for u := range cw.watchedUsers { + globalApp.cache.Watch(u) + } +} + +func (cw *channelWindow) Buffer() *buffer.Buffer { + return &cw.buf +} + +func (cw *channelWindow) Input() *tui.TextInput { + return &cw.input +} + +func (cw *channelWindow) Send(text string) { + if !globalApp.connected || !globalApp.authenticated { + return + } + cb := func(response proto.Command) { + switch response.Kind { + case "p": + if len(response.Args) > 0 { + cw.put(response.Args[0]) + } + case "fail": + if len(response.Args) > 0 { + f := proto.Fail(response.Args[0]) + globalApp.cmdWindow.err(f.Error()) + } + } + } + msg := proto.Object {"m", "", map[string]string {"": text}} + globalApp.Request(proto.NewCmd("p", cw.location.id, msg), cb) + cw.input.SetText("") +} + +func (cw *channelWindow) ShowStatusLine() { + ch := cw.getChannel() + if ch == nil { + return + } + tui.Text(ch.Fields[""], nil) + if cw.loadingHistory { + tui.Text("...", nil) + } +} + +func (m channelMsg) Id() string { + return m.Object.Id +} + +func (m channelMsg) showDate(bg int32) { + unix, _ := strconv.Atoi(m.Fields["t"]) + time := time.Unix(int64(unix), 0).Format(time.DateTime) + tui.Push("", tui.Box {Width: tui.TextSize, Height: 1, NoWrap: true}) + tui.Text(" " + time, &tui.Style {Fg: tui.BrightBlack, Bg: bg}) + tui.Pop() + tui.Push("", tui.Box {Width: tui.Fill, Height: 1}) + tui.Pop() +} + +func (m channelMsg) Show(odd bool) { + var bg int32 = tui.Black + if odd { + bg = 236 + } + + switch m.Kind { + case "join": + tui.Push("", tui.Box { + Width: tui.Fill, Height: tui.Children, Dir: tui.Left, + }) + m.showDate(bg) + tui.Push("", tui.Box {Width: tui.TextSize, Height: tui.TextSize}) + tui.Text("-> ", &tui.Style {Fg: tui.BrightBlack, Bg: bg}) + tui.Text("join", &tui.Style {Fg: tui.Blue, Bg: bg, Bold: true}) + tui.Text(": ", &tui.Style {Fg: tui.BrightBlack, Bg: bg}) + tui.Text(m.window.username(m.Fields[""]), nil) + tui.Pop() + tui.Pop() + case "leave": + tui.Push("", tui.Box { + Width: tui.Fill, Height: tui.Children, Dir: tui.Left, + }) + m.showDate(bg) + tui.Push("", tui.Box {Width: tui.TextSize, Height: tui.TextSize}) + tui.Text("<- ", &tui.Style {Fg: tui.BrightBlack, Bg: bg}) + tui.Text("leave", &tui.Style {Fg: tui.Blue, Bg: bg, Bold: true}) + tui.Text(": ", &tui.Style {Fg: tui.BrightBlack, Bg: bg}) + tui.Text(m.window.username(m.Fields[""]), nil) + tui.Pop() + tui.Pop() + case "m": + var usernameFg int32 = tui.White + if m.Fields["f"] == globalApp.uid { + usernameFg = tui.Cyan + } + + tui.Push("", tui.Box {Width: tui.Fill, Height: 1, Dir: tui.Left}) + m.showDate(bg) + tui.Push("", tui.Box {Width: tui.TextSize, Height: 1, NoWrap: true}) + tui.Text(m.window.username(m.Fields["f"]), &tui.Style { + Fg: usernameFg, Bg: bg, Bold: true, + }) + tui.Pop() + tui.Pop() + + tui.Push("", tui.Box { + Width: tui.TextSize, Height: tui.TextSize, + Margins: [4]int {1, 0, 0, 0}, + }) + tui.Text(m.Fields[""], nil) + tui.Pop() + default: + tui.Push("", tui.Box {Width: tui.Fill, Height: tui.TextSize}) + tui.Text("[", nil) + tui.Text(m.Kind, &tui.Style {Fg: tui.White, Bg: bg, Italic: true}) + tui.Text("]", nil) + tui.Pop() + } +} -- cgit v1.2.3