aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md2
-rw-r--r--main.go23
-rw-r--r--web/client.html34
-rw-r--r--wrms.go17
4 files changed, 55 insertions, 21 deletions
diff --git a/TODO.md b/TODO.md
index d8231a0..b618a8e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -9,7 +9,7 @@
- [X] escape HTML
- [X] support incremental search results
- - [ ] distinguish different search queries
+ - [X] distinguish different search queries
## Web Backend
diff --git a/main.go b/main.go
index 8d84317..2899eb1 100644
--- a/main.go
+++ b/main.go
@@ -8,6 +8,7 @@ import (
"html/template"
"io"
"net/http"
+ "strconv"
"strings"
"time"
@@ -79,6 +80,16 @@ func searchHandler(w http.ResponseWriter, r *http.Request) {
}
pattern := r.URL.Query().Get("pattern")
+ if pattern == "" {
+ http.Error(w, "No search pattern provided", http.StatusBadRequest)
+ return
+ }
+
+ id, ok := strconv.Atoi(r.URL.Query().Get("id"))
+ if ok != err {
+ http.Error(w, "No or invalid search id provided", http.StatusBadRequest)
+ return
+ }
llog.Debug("Searching for %s", pattern)
@@ -88,11 +99,11 @@ func searchHandler(w http.ResponseWriter, r *http.Request) {
go func() {
for result := range resultsChan {
if len(result) > 0 {
- conn.Send(Event{"search", result})
+ conn.Send(newSearchResultEvent(id, result))
}
}
- conn.Send(newNotification("finish-search"))
+ conn.Send(Event{Event: "finish-search", Id: id})
llog.Debug("searching for %s took %v", pattern, time.Since(start))
}()
@@ -187,7 +198,7 @@ func wsEndpoint(w http.ResponseWriter, r *http.Request) {
initialCmds := [][]byte{}
if wrms.Playing {
- data, err := json.Marshal(Event{"play", []Song{wrms.CurrentSong}})
+ data, err := json.Marshal(newEvent("play", []Song{wrms.CurrentSong}))
if err != nil {
llog.Error("Encoding the play event failed with %s", err)
return
@@ -198,7 +209,7 @@ func wsEndpoint(w http.ResponseWriter, r *http.Request) {
upvoted := []Song{}
downvoted := []Song{}
if len(wrms.Songs) > 0 {
- data, err := json.Marshal(Event{"add", wrms.Songs})
+ data, err := json.Marshal(newEvent("add", wrms.Songs))
if err != nil {
llog.Error("Encoding the add event failed with %s", err)
return
@@ -215,7 +226,7 @@ func wsEndpoint(w http.ResponseWriter, r *http.Request) {
}
if len(upvoted) > 0 {
- data, err := json.Marshal(Event{"upvoted", upvoted})
+ data, err := json.Marshal(newEvent("upvoted", upvoted))
if err != nil {
llog.Error("Encoding the upvoted event failed with %s", err)
return
@@ -224,7 +235,7 @@ func wsEndpoint(w http.ResponseWriter, r *http.Request) {
}
if len(downvoted) > 0 {
- data, err := json.Marshal(Event{"downvoted", downvoted})
+ data, err := json.Marshal(newEvent("downvoted", downvoted))
if err != nil {
llog.Error("Encoding the upvoted event failed with %s", err)
return
diff --git a/web/client.html b/web/client.html
index 0f94c45..20aa7ad 100644
--- a/web/client.html
+++ b/web/client.html
@@ -73,6 +73,7 @@
}
let isAdmin = false;
+ let searchId = 0;
let songs = [];
let playing = {};
let votes = new Map();
@@ -237,10 +238,10 @@
handleVotes("down", cmd.songs)
break;
case "search":
- handleSearch(cmd.songs)
+ handleSearch(cmd.id, cmd.songs)
break;
case "finish-search":
- handleFinishSearch()
+ handleFinishSearch(cmd.id)
break;
}
};
@@ -250,9 +251,7 @@
};
function submitSearch() {
- // Clear search Results
- let searchResults = document.getElementById("searchResults");
- searchResults.innerHTML = "";
+ resetSearch();
let searchingIndicator = document.getElementById("searching");
searchingIndicator.style.display = "block";
@@ -260,8 +259,9 @@
searchResultsOverlay['aria-busy'] = true;
const form = new FormData(document.getElementById("searchForm"));
- const pattern = new URLSearchParams(form).toString();
- new HttpClient().get("/search?" + pattern, console.log);
+ const urlParams = new URLSearchParams(form);
+ urlParams.append("id", searchId);
+ new HttpClient().get("/search?" + urlParams.toString(), console.log);
return false;
}
@@ -281,21 +281,27 @@
new HttpClient().post("/add", JSON.stringify(song), console.log);
}
- function handleFinishSearch() {
+ function handleFinishSearch(id) {
+ // Ignore stale finish search notifications
+ if (id < searchId) { return; }
+
let searchingIndicator = document.getElementById("searching");
searchingIndicator.style.display = "none";
let searchResultsOverlay = document.getElementById("searchResultsOverlay");
searchResultsOverlay['aria-busy'] = false;
+ searchId += 1;
}
- function handleSearch(songs) {
+ function handleSearch(id, songs) {
+ // Ignore stale search results
+ if (id < searchId) { return; }
+
let searchResultsOverlay = document.getElementById("searchResultsOverlay");
let searchResults = document.getElementById("searchResults");
for (const song of songs) {
let listItem = document.createElement("li");
listItem.addEventListener("click", function() {
addSong(song);
- searchResultsOverlay.style.display = "none";
});
listItem.classList.add("searchResult")
@@ -308,6 +314,14 @@
searchResultsOverlay.style.display = "block";
}
+ function resetSearch() {
+ // Clear search Results
+ let searchResults = document.getElementById("searchResults");
+ searchResults.innerHTML = "";
+
+ searchId += 1;
+ }
+
window.onload = function() {
{{if .IsAdmin}}
document.getElementById("ppbutton").addEventListener("click", function() {
diff --git a/wrms.go b/wrms.go
index 6dc7af8..430e5a9 100644
--- a/wrms.go
+++ b/wrms.go
@@ -40,11 +40,20 @@ func NewSongFromJson(data []byte) (Song, error) {
type Event struct {
Event string `json:"cmd"`
+ Id int `json:"id"`
Songs []Song `json:"songs"`
}
+func newEvent(event string, songs []Song) Event {
+ return Event{Event: event, Songs: songs}
+}
+
func newNotification(notification string) Event {
- return Event{notification, nil}
+ return Event{Event: notification}
+}
+
+func newSearchResultEvent(id int, songs []Song) Event {
+ return Event{Event: "search", Id: id, Songs: songs}
}
type Connection struct {
@@ -100,7 +109,7 @@ func (wrms *Wrms) Broadcast(ev Event) {
}
func (wrms *Wrms) startPlaying() {
- wrms.Broadcast(Event{"play", []Song{wrms.CurrentSong}})
+ wrms.Broadcast(newEvent("play", []Song{wrms.CurrentSong}))
wrms.Player.Play(&wrms.CurrentSong)
}
@@ -110,7 +119,7 @@ func (wrms *Wrms) AddSong(song Song) {
s := &wrms.Songs[len(wrms.Songs)-1]
wrms.queue.Add(s)
llog.Info("Added song %s (ptr=%p) to Songs", s.Uri, s)
- wrms.Broadcast(Event{"add", []Song{song}})
+ wrms.Broadcast(newEvent("add", []Song{song}))
if startPlayingAgain {
wrms.Next()
@@ -218,7 +227,7 @@ func (wrms *Wrms) AdjustSongWeight(connId uuid.UUID, songUri string, vote string
}
wrms.queue.Adjust(s)
- wrms.Broadcast(Event{"update", []Song{*s}})
+ wrms.Broadcast(newEvent("update", []Song{*s}))
break
}
}