feat: add snake multiplayer chat as sidebar with vivid player colors

Move chat to the right of the board using a flex wrapper that stacks
vertically on narrow screens. Restore original snake player colors by
removing the desaturation filter added with the dark theme.
This commit is contained in:
Ryan Hamamura
2026-02-05 10:15:26 -10:00
parent 0279615b36
commit 3d019fd948
4 changed files with 248 additions and 10 deletions

66
main.go
View File

@@ -6,9 +6,12 @@ import (
"database/sql"
_ "embed"
"encoding/hex"
"encoding/json"
"log"
"net/http"
"os"
"sync"
"time"
"github.com/google/uuid"
"github.com/joho/godotenv"
@@ -588,8 +591,51 @@ func main() {
}
})
chatMsg := c.Signal("")
var chatMessages []ui.ChatMessage
var chatMu sync.Mutex
sendChat := c.Action(func() {
msg := chatMsg.String()
if msg == "" || si == nil {
return
}
slot := si.GetPlayerSlot(playerID)
if slot < 0 {
return
}
cm := ui.ChatMessage{
Nickname: si.GetGame().Players[slot].Nickname,
Slot: slot,
Message: msg,
Time: time.Now().UnixMilli(),
}
data, err := json.Marshal(cm)
if err != nil {
return
}
c.Publish("snake.chat."+gameID, data)
chatMsg.SetValue("")
})
if gameExists {
c.Subscribe("snake."+gameID, func(data []byte) { c.Sync() })
if si.GetGame().Mode == snake.ModeMultiplayer {
c.Subscribe("snake.chat."+gameID, func(data []byte) {
var cm ui.ChatMessage
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()
})
}
}
// Auto-join if nickname exists
@@ -638,7 +684,25 @@ func main() {
)
if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
content = append(content, ui.SnakeBoard(sg))
board := ui.SnakeBoard(sg)
if sg.Mode == snake.ModeMultiplayer {
chatMu.Lock()
msgs := make([]ui.ChatMessage, len(chatMessages))
copy(msgs, chatMessages)
chatMu.Unlock()
chat := ui.SnakeChat(msgs, chatMsg.Bind(), sendChat.OnClick(), sendChat.OnKeyDown("Enter"))
content = append(content, h.Div(h.Class("snake-game-area"), board, chat))
} else {
content = append(content, board)
}
} else if sg.Mode == snake.ModeMultiplayer {
// Show chat even before game starts (waiting/countdown)
chatMu.Lock()
msgs := make([]ui.ChatMessage, len(chatMessages))
copy(msgs, chatMessages)
chatMu.Unlock()
content = append(content, ui.SnakeChat(msgs, chatMsg.Bind(), sendChat.OnClick(), sendChat.OnKeyDown("Enter")))
}
// Only show invite link for multiplayer games