Multi-Room Chat (#4)

* # This is a combination of 4 commits.
# This is the 1st commit message:

Chatroom example

# This is the commit message #2:

Avatar styling

# This is the commit message #3:

Styling

# This is the commit message #4:

cleanup

* Chatroom example

Avatar styling

Benchmark tests

Cleanup

ignore

Files

Cleanroom chatroom impl

* Rewrite.

* changes

* Fix Deadlocks. Start the rooms. Fix styling. Random things. Bookmarklet.

* Subset data

* Rm file

* Simplify User. Just Comparable.

* Remove method.
This commit is contained in:
Jeff Winkler
2025-11-11 18:30:40 -05:00
committed by GitHub
parent 5e9740813b
commit 779718a088
7 changed files with 637 additions and 9 deletions

View File

@@ -2,6 +2,7 @@ package via
import (
"fmt"
"strconv"
"github.com/go-via/via/h"
)
@@ -11,14 +12,85 @@ type actionTrigger struct {
id string
}
// OnClick returns a via.h DOM node that triggers on click. It can be added
// to element nodes in a view.
func (a *actionTrigger) OnClick() h.H {
return h.Data("on:click", fmt.Sprintf("@get('/_action/%s')", a.id))
// ActionTriggerOption configures behavior of action triggers
type ActionTriggerOption interface {
apply(*triggerOpts)
}
// OnChange returns a via.h DOM node that triggers on input change. It can be added
// to element nodes in a view.
func (a *actionTrigger) OnChange() h.H {
return h.Data("on:change__debounce.200ms", fmt.Sprintf("@get('/_action/%s')", a.id))
type triggerOpts struct {
hasSignal bool
signalID string
value string
}
type withSignalOpt struct {
signalID string
value string
}
func (o withSignalOpt) apply(opts *triggerOpts) {
opts.hasSignal = true
opts.signalID = o.signalID
opts.value = o.value
}
// WithSignal sets a signal value before triggering the action.
func WithSignal(sig *signal, value string) ActionTriggerOption {
return withSignalOpt{
signalID: sig.ID(),
value: fmt.Sprintf("'%s'", value),
}
}
// WithSignalInt sets a signal to an int value before triggering the action.
func WithSignalInt(sig *signal, value int) ActionTriggerOption {
return withSignalOpt{
signalID: sig.ID(),
value: strconv.Itoa(value),
}
}
func buildOnExpr(base string, opts *triggerOpts) string {
if !opts.hasSignal {
return base
}
return fmt.Sprintf("$%s=%s;%s", opts.signalID, opts.value, base)
}
func applyOptions(options ...ActionTriggerOption) triggerOpts {
var opts triggerOpts
for _, opt := range options {
opt.apply(&opts)
}
return opts
}
func actionURL(id string) string {
return fmt.Sprintf("@get('/_action/%s')", id)
}
// OnClick returns a via.h DOM attribute that triggers on click. It can be added
// to element nodes in a view.
func (a *actionTrigger) OnClick(options ...ActionTriggerOption) h.H {
opts := applyOptions(options...)
return h.Data("on:click", buildOnExpr(actionURL(a.id), &opts))
}
// OnChange returns a via.h DOM attribute that triggers on input change. It can be added
// to element nodes in a view.
func (a *actionTrigger) OnChange(options ...ActionTriggerOption) h.H {
opts := applyOptions(options...)
return h.Data("on:change__debounce.200ms", buildOnExpr(actionURL(a.id), &opts))
}
// OnEnterKey returns a via.h DOM attribute that triggers when a key is pressed.
// key: optional, see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
// Example: OnKeyDown("Enter")
func (a *actionTrigger) OnKeyDown(key string, options ...ActionTriggerOption) h.H {
opts := applyOptions(options...)
var condition string
if key != "" {
condition = fmt.Sprintf("evt.key==='%s' &&", key)
}
return h.Data("on:keydown", fmt.Sprintf("%s%s", condition, buildOnExpr(actionURL(a.id), &opts)))
}