feat: add in-game chat to Connect 4
All checks were successful
Deploy c4 / deploy (push) Successful in 43s
All checks were successful
Deploy c4 / deploy (push) Successful in 43s
Add real-time chat alongside the game board, mirroring the snake chat implementation. Fix mobile layout for both C4 and snake chats — expand chat to full width and reduce history height on small screens.
This commit is contained in:
56
main.go
56
main.go
@@ -353,6 +353,9 @@ func main() {
|
||||
nickname := c.Signal(sessionNickname)
|
||||
colSignal := c.Signal(0)
|
||||
showGuestPrompt := c.Signal(false)
|
||||
chatMsg := c.Signal("")
|
||||
var chatMessages []ui.C4ChatMessage
|
||||
var chatMu sync.Mutex
|
||||
|
||||
goToLogin := c.Action(func() {
|
||||
c.Session().Set("return_url", "/game/"+gameID)
|
||||
@@ -434,8 +437,53 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
sendChat := c.Action(func() {
|
||||
msg := chatMsg.String()
|
||||
if msg == "" || gi == nil {
|
||||
return
|
||||
}
|
||||
color := gi.GetPlayerColor(playerID)
|
||||
if color == 0 {
|
||||
return
|
||||
}
|
||||
g := gi.GetGame()
|
||||
nick := ""
|
||||
for _, p := range g.Players {
|
||||
if p != nil && p.ID == playerID {
|
||||
nick = p.Nickname
|
||||
break
|
||||
}
|
||||
}
|
||||
cm := ui.C4ChatMessage{
|
||||
Nickname: nick,
|
||||
Color: color,
|
||||
Message: msg,
|
||||
Time: time.Now().UnixMilli(),
|
||||
}
|
||||
data, err := json.Marshal(cm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.Publish("game.chat."+gameID, data)
|
||||
chatMsg.SetValue("")
|
||||
})
|
||||
|
||||
if gameExists {
|
||||
c.Subscribe("game."+gameID, func(data []byte) { c.Sync() })
|
||||
|
||||
c.Subscribe("game.chat."+gameID, func(data []byte) {
|
||||
var cm ui.C4ChatMessage
|
||||
if err := json.Unmarshal(data, &cm); err != nil {
|
||||
return
|
||||
}
|
||||
chatMu.Lock()
|
||||
chatMessages = append(chatMessages, cm)
|
||||
if len(chatMessages) > 50 {
|
||||
chatMessages = chatMessages[len(chatMessages)-50:]
|
||||
}
|
||||
chatMu.Unlock()
|
||||
c.Sync()
|
||||
})
|
||||
}
|
||||
|
||||
if gameExists && sessionNickname != "" && gi.GetPlayerColor(playerID) == 0 {
|
||||
@@ -480,13 +528,19 @@ func main() {
|
||||
return dropPiece.OnClick(via.WithSignalInt(colSignal, col))
|
||||
}
|
||||
|
||||
chatMu.Lock()
|
||||
msgs := make([]ui.C4ChatMessage, len(chatMessages))
|
||||
copy(msgs, chatMessages)
|
||||
chatMu.Unlock()
|
||||
chat := ui.C4Chat(msgs, chatMsg.Bind(), sendChat.OnClick(), sendChat.OnKeyDown("Enter"))
|
||||
|
||||
var content []h.H
|
||||
content = append(content,
|
||||
ui.BackToLobby(),
|
||||
ui.StealthTitle("text-3xl font-bold"),
|
||||
ui.PlayerInfo(g, myColor),
|
||||
ui.StatusBanner(g, myColor, createRematch.OnClick()),
|
||||
ui.BoardComponent(g, columnClick, myColor),
|
||||
h.Div(h.Class("c4-game-area"), ui.BoardComponent(g, columnClick, myColor), chat),
|
||||
)
|
||||
|
||||
if g.Status == game.StatusWaitingForPlayer {
|
||||
|
||||
Reference in New Issue
Block a user