Generated _templ.go files are deterministic output from .templ sources, same as output.css from input.css. Remove them from version control to reduce diff noise and merge conflicts. Add build:templ and live:templ tasks to the Taskfile so generation happens as part of the build.
67 lines
1.5 KiB
Plaintext
67 lines
1.5 KiB
Plaintext
package components
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ryanhamamura/c4/snake"
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
)
|
|
|
|
type ChatMessage struct {
|
|
Nickname string `json:"nickname"`
|
|
Slot int `json:"slot"`
|
|
Message string `json:"message"`
|
|
Time int64 `json:"time"`
|
|
}
|
|
|
|
templ Chat(messages []ChatMessage, gameID string) {
|
|
<div id="snake-chat" class="snake-chat">
|
|
<div class="snake-chat-history">
|
|
for _, m := range messages {
|
|
<div class="snake-chat-msg">
|
|
<span style={ fmt.Sprintf("color:%s;font-weight:bold;", chatColor(m.Slot)) }>
|
|
{ m.Nickname + ": " }
|
|
</span>
|
|
<span>{ m.Message }</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
<div class="snake-chat-input" data-morph-ignore>
|
|
<input
|
|
type="text"
|
|
placeholder="Chat..."
|
|
autocomplete="off"
|
|
data-bind="chatMsg"
|
|
data-on:keydown.stop=""
|
|
data-on:keydown.key_enter={ datastar.PostSSE("/snake/%s/chat", gameID) }
|
|
/>
|
|
<button
|
|
type="button"
|
|
data-on:click={ datastar.PostSSE("/snake/%s/chat", gameID) }
|
|
>
|
|
Send
|
|
</button>
|
|
</div>
|
|
@chatAutoScroll()
|
|
</div>
|
|
}
|
|
|
|
templ chatAutoScroll() {
|
|
<script>
|
|
(function(){
|
|
var el = document.querySelector('.snake-chat-history');
|
|
if (!el) return;
|
|
el.scrollTop = el.scrollHeight;
|
|
new MutationObserver(function(){ el.scrollTop = el.scrollHeight; })
|
|
.observe(el, {childList:true, subtree:true});
|
|
})();
|
|
</script>
|
|
}
|
|
|
|
func chatColor(slot int) string {
|
|
if slot >= 0 && slot < len(snake.SnakeColors) {
|
|
return snake.SnakeColors[slot]
|
|
}
|
|
return "#666"
|
|
}
|