From e2dc5b6fbb6adf6f379ef0123c214a196211c305 Mon Sep 17 00:00:00 2001 From: citrons Date: Sun, 1 Jun 2025 15:38:17 -0500 Subject: joining channels --- client/application.go | 159 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 118 insertions(+), 41 deletions(-) (limited to 'client/application.go') diff --git a/client/application.go b/client/application.go index 72ec078..b1c5865 100644 --- a/client/application.go +++ b/client/application.go @@ -3,45 +3,49 @@ package main import ( "citrons.xyz/talk/client/client" "citrons.xyz/talk/client/object" - "citrons.xyz/talk/client/buffer" + "citrons.xyz/talk/client/window" "citrons.xyz/talk/proto" - "citrons.xyz/talk/tui" - "zgo.at/termfo/keys" - "os" ) type application struct { client.Client + quit bool + connected bool reconnecting bool authenticated bool uid string cache object.ObjCache - currentBuffer *buffer.Buffer - cmdBuffer cmdBuffer + windowCache window.WindowCache + currentWindow window.Location + cmdWindow cmdWindow } func newApplication(serverAddress string) *application { var app application app.Client = client.New(serverAddress) + app.currentWindow = app.cmdWindow.Location() app.cache = object.NewCache(&app) - app.currentBuffer = &app.cmdBuffer.Buffer + app.windowCache = window.NewCache() - app.cmdBuffer.info("connecting to %s", app.Client.Address) + app.cmdWindow.info("connecting to %s", app.Client.Address) return &app } func (a *application) OnConnect() { + a.connected = true a.reconnecting = false - a.cmdBuffer.info("connected to %s", a.Client.Address) - - a.auth("test user") + a.cache = object.NewCache(a) + a.windowCache = window.NewCache() + a.cmdWindow.info("connected to %s", a.Client.Address) + a.cmdWindow.loginMode() } func (a *application) OnDisconnect(err error) { + a.connected = false a.authenticated = false a.uid = "" if !a.reconnecting { - a.cmdBuffer.err( + a.cmdWindow.err( "disconnected from %s: %s\nreconnecting...", a.Client.Address, err, ) a.reconnecting = true @@ -50,6 +54,11 @@ func (a *application) OnDisconnect(err error) { func (a *application) OnEvent(cmd proto.Command) { switch cmd.Kind { + case "p": + cw := a.windowCache.Get(channelLocation {cmd.Target}).(*channelWindow) + if cw != nil && len(cmd.Args) > 0 { + cw.put(cmd.Args[0]) + } case "update": if len(cmd.Args) > 0 { a.cache.Update(cmd.Target, cmd.Args[0]) @@ -63,7 +72,7 @@ func (a *application) OnResponse(requestId string, cmd proto.Command) { switch cmd.Kind { case "you-are": if len(cmd.Args) > 0 { - a.cmdBuffer.info("your name is: %s", cmd.Args[0].Fields[""]) + a.cmdWindow.info("your name is: %s", cmd.Args[0].Fields[""]) } } } @@ -84,19 +93,28 @@ func (a *application) GetInfo(id string, callback func(proto.Command)) { a.Request(proto.NewCmd("i", id), callback) } -func (a *application) auth(name string) { +func (a *application) auth(name string, authCallback func(success bool)) { callback := func(response proto.Command) { switch response.Kind { case "you-are": if len(response.Args) == 0 { + authCallback(false) break } me := response.Args[0] a.authenticated = true a.uid = me.Id a.cache.Watch(a.uid) + if authCallback != nil { + authCallback(true) + } case "fail": - // todo + if len(response.Args) != 0 { + a.cmdWindow.err(proto.Strfail(response.Args[0])) + } + if authCallback != nil { + authCallback(false) + } } } a.Request(proto.NewCmd("auth", "", proto.Object { @@ -104,39 +122,98 @@ func (a *application) auth(name string) { }), callback) } -func (a *application) onInput(ev tui.Event) { - tui.Selected = "input" +func (a *application) sendUpdate(o proto.Object, cb func(proto.Command)) { + a.Request(proto.NewCmd("update", o.Id, o), func(response proto.Command) { + if response.Kind == "ok" { + a.cache.Update(o.Id, o) + } + cb(response) + }) +} - a.currentBuffer.Scroll(-ev.Mouse.Scroll * 2) - scroll := tui.Size().Height - 5 - switch ev.Key { - case keys.PageUp: - a.currentBuffer.Scroll(scroll) - case keys.PageDown: - a.currentBuffer.Scroll(-scroll) +func (a *application) lookup( + name string, kind string, callback func(*proto.Object, *proto.Fail)) { + cb := func(response proto.Command) { + switch response.Kind { + case "i": + if len(response.Args) > 0 { + callback(&response.Args[0], nil) + } + case "fail": + if len(response.Args) > 0 { + f := proto.Fail(response.Args[0]) + callback(nil, &f) + } + } } - - a.currentBuffer.TextInput.Update(ev) + o := proto.Object {kind, "", map[string]string {"": name}} + a.Request(proto.NewCmd("lookup", "", o), cb) } -func (a *application) show() { - tui.Clear() - s := tui.Size() - tui.Push("", tui.Box { - Width: tui.BoxSize(s.Width), Height: tui.BoxSize(s.Height), +func (a *application) join(channelName string) { + a.lookup(channelName, "channel", func(ch *proto.Object, f *proto.Fail) { + if f != nil { + a.cmdWindow.err(f.Error()) + return + } + a.Request(proto.NewCmd("join", ch.Id), func(response proto.Command) { + switch response.Kind { + case "ok": + a.currentWindow = channelLocation {id: ch.Id} + case "fail": + if len(response.Args) > 0 { + f := proto.Fail(response.Args[0]) + a.cmdWindow.err(f.Error()) + } + } + }) }) +} - a.currentBuffer.Show("buffer") - tui.Push("status", tui.Box { - Width: tui.Fill, Height: tui.BoxSize(1), Dir: tui.Right, - Style: &tui.Style {Bg: tui.White, Fg: tui.Black}, +func (a *application) createChannel(name string) { + ch := proto.Object {"channel", "", map[string]string {"": name}} + a.Request(proto.NewCmd("create", "", ch), func(response proto.Command) { + switch response.Kind { + case "create": + if len(response.Args) > 0 { + ch := response.Args[0] + a.currentWindow = channelLocation {id: ch.Id} + } + case "fail": + if len(response.Args) > 0 { + f := proto.Fail(response.Args[0]) + a.cmdWindow.err(f.Error()) + } + } }) - tui.Pop() - a.currentBuffer.TextInput.Show("input") +} + +func (a *application) getNick() string { + if !a.authenticated { + return "" + } + u := a.cache.Get(a.uid) + if u != nil { + return u.Fields[""] + } + return "" +} - tui.Pop() - tui.DrawLayout() - if tui.Present() != nil { - os.Exit(-1) +func (a *application) setNick(newName string) { + if !a.authenticated { + return + } + callback := func(response proto.Command) { + switch response.Kind { + case "fail": + if len(response.Args) != 0 { + a.cmdWindow.err(proto.Strfail(response.Args[0])) + } + case "ok": + a.cmdWindow.info("your name is: %s", newName) + } } + a.sendUpdate( + proto.Object {"u", a.uid, map[string]string {"": newName}}, callback, + ) } -- cgit v1.2.3