Fixed broken chat reading.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# shellcheck shell=bash disable=SC2034,SC2154
|
# shellcheck shell=bash disable=SC2034,SC2154
|
||||||
|
|
||||||
pkgname=skald-git
|
pkgname=skald-git
|
||||||
pkgver=0.0.0.r1537.g7cfbcda
|
pkgver=0.0.0.r1538.g8e265ed
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc='Audio-only hall-based conferencing server'
|
pkgdesc='Audio-only hall-based conferencing server'
|
||||||
arch=('x86_64' 'aarch64')
|
arch=('x86_64' 'aarch64')
|
||||||
|
|||||||
+39
-2
@@ -2589,6 +2589,10 @@ function formatTime(time) {
|
|||||||
/** @type {lastMessage} */
|
/** @type {lastMessage} */
|
||||||
let lastMessage = {};
|
let lastMessage = {};
|
||||||
|
|
||||||
|
/** @type {Object.<string, {queue: string[], active: boolean}>} */
|
||||||
|
let liveRegionStates = {};
|
||||||
|
let liveRegionDelay = 700;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} text
|
* @param {string} text
|
||||||
* @param {string} elementId
|
* @param {string} elementId
|
||||||
@@ -2598,9 +2602,42 @@ function announceLiveRegion(text, elementId) {
|
|||||||
if(!announcement)
|
if(!announcement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
announcement.textContent = '';
|
let state = liveRegionStates[elementId];
|
||||||
|
if(!state) {
|
||||||
|
state = {queue: [], active: false};
|
||||||
|
liveRegionStates[elementId] = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.queue.push(String(text));
|
||||||
|
if(!state.active)
|
||||||
|
flushLiveRegion(elementId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} elementId
|
||||||
|
*/
|
||||||
|
function flushLiveRegion(elementId) {
|
||||||
|
let state = liveRegionStates[elementId];
|
||||||
|
let announcement = document.getElementById(elementId);
|
||||||
|
if(!state || !announcement) {
|
||||||
|
if(state)
|
||||||
|
state.active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = state.queue.shift();
|
||||||
|
if(text === undefined) {
|
||||||
|
state.active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.active = true;
|
||||||
|
announcement.replaceChildren();
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
announcement.textContent = text;
|
let item = document.createElement('div');
|
||||||
|
item.textContent = text;
|
||||||
|
announcement.appendChild(item);
|
||||||
|
window.setTimeout(() => flushLiveRegion(elementId), liveRegionDelay);
|
||||||
}, 20);
|
}, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readStaticFile(t *testing.T, name string) string {
|
||||||
|
t.Helper()
|
||||||
|
data, err := os.ReadFile(filepath.Join("..", "static", name))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read %s: %v", name, err)
|
||||||
|
}
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireContains(t *testing.T, text, want, context string) {
|
||||||
|
t.Helper()
|
||||||
|
if !strings.Contains(text, want) {
|
||||||
|
t.Fatalf("%s missing %q", context, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireFunctionContains(t *testing.T, source, functionName, want string) {
|
||||||
|
t.Helper()
|
||||||
|
start := strings.Index(source, "function "+functionName+"(")
|
||||||
|
if start < 0 {
|
||||||
|
t.Fatalf("missing function %s", functionName)
|
||||||
|
}
|
||||||
|
next := strings.Index(source[start+1:], "\nfunction ")
|
||||||
|
end := len(source)
|
||||||
|
if next >= 0 {
|
||||||
|
end = start + 1 + next
|
||||||
|
}
|
||||||
|
body := source[start:end]
|
||||||
|
if !strings.Contains(body, want) {
|
||||||
|
t.Fatalf("function %s missing %q", functionName, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStaticLiveRegionAnnouncementsStayWired(t *testing.T) {
|
||||||
|
html := readStaticFile(t, "skald.html")
|
||||||
|
js := readStaticFile(t, "skald.js")
|
||||||
|
|
||||||
|
requireContains(t, html, `id="chat-announcements"`, "chat live region")
|
||||||
|
requireContains(t, html, `role="status"`, "chat live region")
|
||||||
|
requireContains(t, html, `aria-live="polite"`, "chat live region")
|
||||||
|
requireContains(t, html, `id="urgent-announcements"`, "urgent live region")
|
||||||
|
requireContains(t, html, `role="alert"`, "urgent live region")
|
||||||
|
requireContains(t, html, `aria-live="assertive"`, "urgent live region")
|
||||||
|
|
||||||
|
requireFunctionContains(t, js, "announceChat", "chat-announcements")
|
||||||
|
requireFunctionContains(t, js, "announceUrgent", "urgent-announcements")
|
||||||
|
requireFunctionContains(t, js, "announceLiveRegion", "state.queue.push")
|
||||||
|
requireFunctionContains(t, js, "announceLiveRegion", "flushLiveRegion")
|
||||||
|
requireFunctionContains(t, js, "flushLiveRegion", "appendChild")
|
||||||
|
requireFunctionContains(t, js, "addToChatbox", "announceChat")
|
||||||
|
requireFunctionContains(t, js, "setUserStatus", "announceUrgent(`${username}: hand raised`)")
|
||||||
|
requireFunctionContains(t, js, "setUserStatus", "announceUrgent(`${username}: hand lowered`)")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user