feat: separate 'speaker controls'

specifically for 'i have finished speaking' and not allowing to change
the state
This commit is contained in:
efim 2023-11-25 08:42:13 +00:00
parent 1b91b9f083
commit 85b3a3f89e
4 changed files with 111 additions and 63 deletions

View File

@ -41,6 +41,8 @@ func registerPageRoutes(
http.StripPrefix(subscribeRoomPath, streamingRoomStates(templateFs, roomsM)))) http.StripPrefix(subscribeRoomPath, streamingRoomStates(templateFs, roomsM))))
http.HandleFunc("/rooms/preview-templates", roomTemplatesPreview(templateFs)) http.HandleFunc("/rooms/preview-templates", roomTemplatesPreview(templateFs))
http.HandleFunc("/rooms/speakerControls", speakerControlsRoute(templateFs))
} }
func streamingRoomStates( func streamingRoomStates(
@ -77,7 +79,7 @@ func streamingRoomStates(
roomStream := roomsM.Subscribe(r.Context(), roomName) roomStream := roomsM.Subscribe(r.Context(), roomName)
for room := range roomStream { for room := range roomStream {
// log.Printf("/rooms/streamingRoom iterating with %+v", room) // log.Printf("/rooms/streamingRoom iterating with %+v", room)
fmt.Fprint(w, "data: ") fmt.Fprint(w, "event: roomTableUpdate\ndata: ")
var buffer bytes.Buffer var buffer bytes.Buffer
@ -96,6 +98,11 @@ func streamingRoomStates(
fmt.Fprint(w, "\n\n") fmt.Fprint(w, "\n\n")
w.(http.Flusher).Flush() w.(http.Flusher).Flush()
if session.PersonId == room.CurrentSpeaker {
log.Printf("/rooms/subscribe sending 'become-speaker' to %s", session.PersonId)
fmt.Fprint(w, "event: become-speaker\ndata:yo\n\n")
w.(http.Flusher).Flush()
}
} }
} }
} }
@ -119,8 +126,10 @@ func raiseGestureHandRoute(
// TODO return error i guess // TODO return error i guess
return return
} }
var room rooms.Room
err = roomsM.Update(r.Context(), session.RoomId, func(fromRoom rooms.Room) (toRoom rooms.Room) { err = roomsM.Update(r.Context(), session.RoomId, func(fromRoom rooms.Room) (toRoom rooms.Room) {
toRoom = fromRoom.RaiseHand(session.PersonId, selectedGesture) toRoom = fromRoom.RaiseHand(session.PersonId, selectedGesture)
room = toRoom
return toRoom return toRoom
}) })
if err != nil { if err != nil {
@ -132,19 +141,24 @@ func raiseGestureHandRoute(
tmpl := template.Must( tmpl := template.Must(
template.New("").ParseFS(templateFs, tableTemplates)) template.New("").ParseFS(templateFs, tableTemplates))
var gesturesData []GestureData if session.PersonId == room.CurrentSpeaker {
for _, gesture := range rooms.GesturesHighToLow { tmpl.ExecuteTemplate(w, "speakerControls", nil)
gesturesData = append(gesturesData, GestureData{
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
Gesture: gesture,
IsSelected: selectedGesture == gesture,
})
}
err = tmpl.ExecuteTemplate(w, "controls", &gesturesData)
if err != nil {
log.Printf("/rooms/releaseHand error saving hand: %s\n", err)
return return
// TODO return error i guess } else {
var gesturesData []GestureData
for _, gesture := range rooms.GesturesHighToLow {
gesturesData = append(gesturesData, GestureData{
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
Gesture: gesture,
IsSelected: selectedGesture == gesture,
})
}
err = tmpl.ExecuteTemplate(w, "controls", &gesturesData)
if err != nil {
log.Printf("/rooms/releaseHand error saving hand: %s\n", err)
return
// TODO return error i guess
}
} }
} }
} }
@ -178,8 +192,8 @@ func releaseHandRoute(
var gesturesData []GestureData var gesturesData []GestureData
for _, gesture := range rooms.GesturesHighToLow { for _, gesture := range rooms.GesturesHighToLow {
gesturesData = append(gesturesData, GestureData{ gesturesData = append(gesturesData, GestureData{
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture), Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
Gesture: gesture, Gesture: gesture,
IsSelected: false, IsSelected: false,
}) })
} }
@ -192,7 +206,6 @@ func releaseHandRoute(
} }
} }
func roomPageRoute( func roomPageRoute(
templateFs *embed.FS, templateFs *embed.FS,
roomsM rooms.RoomManager, roomsM rooms.RoomManager,
@ -236,8 +249,8 @@ func roomPageRoute(
selectedGesture, isSelected := room.ParticipantHands[session.PersonId] selectedGesture, isSelected := room.ParticipantHands[session.PersonId]
for _, gesture := range rooms.GesturesHighToLow { for _, gesture := range rooms.GesturesHighToLow {
gesturesData = append(gesturesData, GestureData{ gesturesData = append(gesturesData, GestureData{
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture), Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
Gesture: gesture, Gesture: gesture,
IsSelected: isSelected && selectedGesture == gesture, IsSelected: isSelected && selectedGesture == gesture,
}) })
} }
@ -269,8 +282,18 @@ func roomPageRoute(
} }
} }
func speakerControlsRoute(
templateFs *embed.FS,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
templateFile := "templates/room.gohtml"
tmpl := template.Must(template.ParseFS(templateFs, templateFile))
tmpl.ExecuteTemplate(w, "speakerControls", nil)
}
}
type GestureData struct { type GestureData struct {
Url string Url string
Gesture rooms.HandGesture Gesture rooms.HandGesture
IsSelected bool IsSelected bool
} }

View File

@ -57,6 +57,9 @@ func (r *roomTableData) Tangens() float64 {
} }
return math.Tan(math.Pi / float64(r.Total())) // Math.tan(Math.PI/m); return math.Tan(math.Pi / float64(r.Total())) // Math.tan(Math.PI/m);
} }
func (r *roomTableData) IsViewerTheSpeaker() bool {
return r.currentPerson == r.CurrentSpeaker
}
type arrowData struct { type arrowData struct {
IsVisible bool IsVisible bool

View File

@ -734,6 +734,11 @@ video {
background-color: hsl(var(--color) / 0.5); background-color: hsl(var(--color) / 0.5);
} }
.bg-blue-100 {
--tw-bg-opacity: 1;
background-color: rgb(219 234 254 / var(--tw-bg-opacity));
}
.bg-green-300 { .bg-green-300 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(134 239 172 / var(--tw-bg-opacity)); background-color: rgb(134 239 172 / var(--tw-bg-opacity));

View File

@ -26,54 +26,71 @@
</p> </p>
<![endif]--> <![endif]-->
{{ define "main-content" }} {{ define "main-content" }}
<main class="h-screen"> <script src="/static/dist/ext/sse.js"></script>
<div class="h-full w-full flex flex-row"> <main class="h-screen w-full flex flex-row"
<script src="/static/dist/ext/sse.js"></script>
{{/* This is dynamic table, updated from SSE */}}
<div
id="roomTextContainer"
class="grid place-content-center grow"
hx-ext="sse" hx-ext="sse"
sse-connect="/rooms/subscribe?roomName={{ .Room.Name }}" sse-connect="/rooms/subscribe?roomName={{ .Room.Name }}">
> {{/* This is dynamic table, updated from SSE */}}
{{ block "simpleRoomShow" .Room }} <section
<!-- TODO use template, not block, have only 'loader' in base place --> id="roomTable"
<!-- use different template based on 'mobile' query param --> class="grid place-content-center grow"
<div sse-swap="message"> >
<div> {{ block "simpleRoomShow" .Room }}
{{ template "roomPeople" . }} <!-- TODO use template, not block, have only 'loader' in base place -->
</div> <!-- use different template based on 'mobile' query param -->
<div sse-swap="roomTableUpdate">
<div>
{{ template "roomPeople" . }}
</div> </div>
{{ end }}
</div> </div>
{{/* This is personal hand controls */}} {{ end }}
<div id="controls" class="bg-green-300 flex flex-col p-10 gap-y-5"> </section>
{{ block "controls" .Gestures }} {{/* This is personal hand controls */}}
{{ range . }} {{ if not .Room.IsViewerTheSpeaker }}
{{ block "controls" .Gestures }}
<section id="controls" class="bg-green-300 flex flex-col p-10 gap-y-5"
hx-trigger="sse:become-speaker"
hx-get="/rooms/speakerControls"
hx-swap="outerHTML"
>
{{ range . }}
{{/* expects routes.GestureData */}} {{/* expects routes.GestureData */}}
<button <button
{{ if not .IsSelected }} {{ if not .IsSelected }}
hx-get="{{ .Url }}" hx-get="{{ .Url }}"
class="bg-white rounded border-[hsl(var(--color))] border-2 text-[hsl(var(--color-dark))] font-bold h-16 rounded-l-full flex flex-row items-center" class="bg-white rounded border-[hsl(var(--color))] border-2 text-[hsl(var(--color-dark))] font-bold h-16 rounded-l-full flex flex-row items-center"
{{ else }} {{ else }}
hx-get="/rooms/releaseHand" hx-get="/rooms/releaseHand"
class="bg-[hsl(var(--color))]/50 rounded border-[hsl(var(--color-dark))] border-2 text-[hsl(var(--text-color))] font-bold h-16 rounded-l-full flex flex-row items-center" class="bg-[hsl(var(--color))]/50 rounded border-[hsl(var(--color-dark))] border-2 text-[hsl(var(--text-color))] font-bold h-16 rounded-l-full flex flex-row items-center"
{{ end }} {{ end }}
hx-target="#controls" hx-target="#controls"
style="--color: var({{.Gesture.GetGestureInfo.Color}}); style="--color: var({{.Gesture.GetGestureInfo.Color}});
--color-dark: var({{.Gesture.GetGestureInfo.ColorDark}}) --color-dark: var({{.Gesture.GetGestureInfo.ColorDark}})
"> ">
<img src="{{.Gesture.GetGestureInfo.IconUrl}}" alt="" <img src="{{.Gesture.GetGestureInfo.IconUrl}}" alt=""
class="h-full" class="h-full"
/> />
<p class="px-5 text-l">{{ .Gesture.String }} </p> <p class="px-5 text-l">{{ .Gesture.String }} </p>
</button> </button>
{{ end }} {{ end }}
{{ end }} </section>
</div> {{ end }}
</div> {{ else }}
{{ block "speakerControls" . }}
<section id="controls" class="bg-blue-100 flex flex-col p-10 gap-y-5"
hx-swap="outerHTML">
<button
hx-get="/rooms/releaseHand"
class="bg-white rounded border border-2 font-bold h-16 rounded-l-full flex flex-row items-center"
hx-target="#controls"
>
<p class="px-5 text-l">I have finished speaking</p>
</button>
</section>
{{ end }}
{{ end }}
</main> </main>
{{ end }} {{ end }}
</body> </body>