diff options
Diffstat (limited to 'xA')
| -rw-r--r-- | xA/xA.go | 184 | 
1 files changed, 174 insertions, 10 deletions
| @@ -15,6 +15,7 @@ import (  	"net"  	"net/url"  	"os" +	"slices"  	"time"  	"fyne.io/fyne/v2" @@ -160,7 +161,7 @@ type buffer struct {  	historyAt            int  } -type callback func(err error, response *RelayResponseData) +type callback func(err string, response *RelayResponseData)  var (  	backendAddress string @@ -176,7 +177,7 @@ var (  	bufferCurrent string  	bufferLast    string -	servers map[string]server +	servers map[string]*server  	// Widgets: @@ -187,6 +188,30 @@ var (  // ----------------------------------------------------------------------------- +func refreshBuffer(b *buffer) { +	// TODO(p): See xW, rewrite the whole buffer view. +} + +func refreshBufferList() { +	// TODO(p): First off, add a buffer list, second, refresh it. +} + +func refreshTopic(topic []bufferLineItem) { +	// TODO(p): First off, add a topic, second, refresh it. +} + +func refreshStatus() { +	// TODO(p): First off, add a status, second, refresh it. +} + +func refreshIcon() { +	// TODO(p): Can we have an icon at all? +} + +func refreshPrompt() { +	// TODO(p): First off, add a prompt, second, refresh it. +} +  func relayReadMessage(r io.Reader) (m RelayEventMessage, ok bool) {  	var length uint32  	if err := binary.Read(r, binary.BigEndian, &length); err != nil { @@ -268,16 +293,43 @@ func relayWriteMessage(conn net.Conn, commandData any) bool {  	return true  } +func relayProcessCallbacks( +	commandSeq uint32, err string, response *RelayResponseData) { +	if handler, ok := commandCallbacks[commandSeq]; !ok { +		// TODO(p): Warn about an unawaited response. +	} else { +		delete(commandCallbacks, commandSeq) +		if handler != nil { +			handler(err, response) +		} +	} + +	// We don't particularly care about wraparound issues. +	for cs, handler := range commandCallbacks { +		if cs <= commandSeq { +			delete(commandCallbacks, cs) +			if handler != nil { +				handler("No response", nil) +			} +		} +	} +} + +func bufferByName(name string) *buffer { +	for i := range buffers { +		if buffers[i].bufferName == name { +			return &buffers[i] +		} +	} +	return nil +} +  func relayProcessMessage(m *RelayEventMessage) {  	switch data := m.Data.Interface.(type) {  	case RelayEventDataError: -		// TODO(p): Process callbacks. -		_ = data.CommandSeq -		_ = data.Error +		relayProcessCallbacks(data.CommandSeq, data.Error, nil)  	case RelayEventDataResponse: -		// TODO(p): Process callbacks. -		_ = data.CommandSeq -		_ = data.Data +		relayProcessCallbacks(data.CommandSeq, "", &data.Data)  	case RelayEventDataPing:  		// TODO(p): Send the command. @@ -286,21 +338,133 @@ func relayProcessMessage(m *RelayEventMessage) {  			EventSeq: m.EventSeq,  		} -		// TODO(p): Process all remaining message kinds.  	case RelayEventDataBufferLine: +		// TODO(p): Process all remaining message kinds.  	case RelayEventDataBufferUpdate: +		b := bufferByName(data.BufferName) +		if b == nil { +			buffers = append(buffers, buffer{}) +			b = &buffers[len(buffers)-1] +			refreshBufferList() +		} + +		hidingToggled := b.hideUnimportant != data.HideUnimportant +		b.hideUnimportant = data.HideUnimportant +		// TODO(p): Change the generator to add a Kind method, +		// so that it always has a proper value. +		//b.kind = data.Context.Kind +		b.serverName = "" +		switch context := data.Context.Interface.(type) { +		case RelayBufferContextServer: +			b.serverName = context.ServerName +		case RelayBufferContextChannel: +			b.serverName = context.ServerName +			b.modes = context.Modes +			// TODO(p): Convert the items. +			b.topic = nil +		case RelayBufferContextPrivateMessage: +			b.serverName = context.ServerName +		} + +		// TODO: Port over the rest as well. +		if b.bufferName == bufferCurrent { +			refreshTopic(b.topic) +			refreshStatus() + +			if hidingToggled { +				refreshBuffer(b) +			} +		}  	case RelayEventDataBufferStats: +		b := bufferByName(data.BufferName) +		if b == nil { +			return +		} + +		b.newMessages = int(data.NewMessages) +		b.newUnimportantMessages = int(data.NewUnimportantMessages) +		b.highlighted = data.Highlighted + +		refreshIcon()  	case RelayEventDataBufferRename: +		b := bufferByName(data.BufferName) +		if b == nil { +			return +		} + +		b.bufferName = data.New + +		refreshBufferList() +		if data.BufferName == bufferCurrent { +			bufferCurrent = data.New +			refreshStatus() +		} +		if data.BufferName == bufferLast { +			bufferLast = data.New +		}  	case RelayEventDataBufferRemove: +		buffers = slices.DeleteFunc(buffers, func(b buffer) bool { +			return b.bufferName == data.BufferName +		}) + +		refreshBufferList() +		refreshIcon()  	case RelayEventDataBufferActivate: +		// TODO(p): Process all remaining message kinds.  	case RelayEventDataBufferInput: +		b := bufferByName(data.BufferName) +		if b == nil { +			return +		} + +		if b.historyAt == len(b.history) { +			b.historyAt++ +		} +		b.history = append(b.history, data.Text)  	case RelayEventDataBufferClear: +		b := bufferByName(data.BufferName) +		if b == nil { +			return +		} + +		b.lines = nil +		if b.bufferName == bufferCurrent { +			refreshBuffer(b) +		}  	case RelayEventDataServerUpdate: +		s, existed := servers[data.ServerName] +		if !existed { +			s = &server{} +			servers[data.ServerName] = s +		} + +		// TODO(p): Change the generator to add a State method, +		// so that it always has a proper value. +		s.user = "" +		s.userModes = "" +		switch state := data.Data.Interface.(type) { +		case *RelayServerDataDisconnected: +			s.state = state.State +		case *RelayServerDataConnecting: +			s.state = state.State +		case *RelayServerDataConnected: +			s.state = state.State +		case *RelayServerDataRegistered: +			s.state = state.State +			s.user = state.User +			s.userModes = state.UserModes +		case *RelayServerDataDisconnecting: +			s.state = state.State +		} + +		refreshPrompt()  	case RelayEventDataServerRename: +		servers[data.New] = servers[data.ServerName] +		delete(servers, data.ServerName)  	case RelayEventDataServerRemove: +		delete(servers, data.ServerName)  	} -  }  func relayRun() { | 
