|
|
|
|
@@ -1,7 +1,7 @@
|
|
|
|
|
package components
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
|
|
|
)
|
|
|
|
|
@@ -48,60 +48,12 @@ templ NicknamePrompt(returnPath string) {
|
|
|
|
|
</main>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isStale(lastPing int64) bool {
|
|
|
|
|
return lastPing == 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var connectionWatcherHandle = templ.NewOnceHandle()
|
|
|
|
|
|
|
|
|
|
// ConnectionIndicator shows a small dot indicating SSE connection status.
|
|
|
|
|
// Server patches this with a timestamp; client JS detects staleness.
|
|
|
|
|
templ ConnectionIndicator(lastPing int64) {
|
|
|
|
|
<div
|
|
|
|
|
id="connection-indicator"
|
|
|
|
|
class="fixed top-2 right-2"
|
|
|
|
|
data-last-ping={ fmt.Sprintf("%d", lastPing) }
|
|
|
|
|
>
|
|
|
|
|
<div class="inline-grid *:[grid-area:1/1]">
|
|
|
|
|
<div
|
|
|
|
|
id="connection-ping"
|
|
|
|
|
class={
|
|
|
|
|
"status status-sm",
|
|
|
|
|
templ.KV("status-success animate-ping", !isStale(lastPing)),
|
|
|
|
|
templ.KV("status-error", isStale(lastPing)),
|
|
|
|
|
}
|
|
|
|
|
></div>
|
|
|
|
|
<div
|
|
|
|
|
id="connection-dot"
|
|
|
|
|
class={
|
|
|
|
|
"status status-sm",
|
|
|
|
|
templ.KV("status-success", !isStale(lastPing)),
|
|
|
|
|
templ.KV("status-error", isStale(lastPing)),
|
|
|
|
|
}
|
|
|
|
|
></div>
|
|
|
|
|
// LiveClock shows the current server time, updated with each SSE patch.
|
|
|
|
|
// If the clock stops updating, users know the connection is stale.
|
|
|
|
|
templ LiveClock() {
|
|
|
|
|
<div class="fixed top-2 right-2 text-xs opacity-50 font-mono">
|
|
|
|
|
{ time.Now().Format("15:04:05") }
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
@connectionWatcherHandle.Once() {
|
|
|
|
|
@connectionWatcher()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
script connectionWatcher() {
|
|
|
|
|
setInterval(function() {
|
|
|
|
|
var el = document.getElementById('connection-indicator');
|
|
|
|
|
var dot = document.getElementById('connection-dot');
|
|
|
|
|
var ping = document.getElementById('connection-ping');
|
|
|
|
|
if (!el || !dot || !ping) return;
|
|
|
|
|
|
|
|
|
|
var lastPing = parseInt(el.dataset.lastPing, 10) || 0;
|
|
|
|
|
var stale = Date.now() - lastPing > 20000;
|
|
|
|
|
|
|
|
|
|
dot.classList.toggle('status-success', !stale);
|
|
|
|
|
dot.classList.toggle('status-error', stale);
|
|
|
|
|
ping.classList.toggle('status-success', !stale);
|
|
|
|
|
ping.classList.toggle('status-error', stale);
|
|
|
|
|
ping.classList.toggle('animate-ping', !stale);
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
templ GameJoinPrompt(loginURL string, registerURL string, gamePath string) {
|
|
|
|
|
|