Compare commits

..

3 Commits

5 changed files with 81 additions and 24 deletions

View File

@ -28,6 +28,11 @@ h2.bot {
} }
.item { .item {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;

View File

@ -3,6 +3,9 @@ package main
import ( import (
"log" "log"
"net/http" "net/http"
"os"
"path"
"path/filepath"
"text/template" "text/template"
"github.com/google/uuid" "github.com/google/uuid"
@ -21,9 +24,8 @@ func init() {
app.router.GET("/", app.Index) app.router.GET("/", app.Index)
app.router.GET("/play/:playlist", app.Play) app.router.GET("/play/:playlist", app.Play)
app.router.GET("/reset", app.Reset) app.router.GET("/reset", app.Reset)
app.router.GET("/public/*js", app.ServeFiles)
app.router.ServeFiles("/js/*filepath", http.Dir("public")) app.router.GET("/css/*css", app.ServeFiles)
app.router.ServeFiles("/css/*filepath", http.Dir("css"))
app.router.HandlerFunc("GET", "/ws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { app.router.HandlerFunc("GET", "/ws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("WS connection from %v\n", r.RemoteAddr) log.Printf("WS connection from %v\n", r.RemoteAddr)
@ -49,6 +51,28 @@ type IndexData struct {
Ambiance []string Ambiance []string
} }
func (app App) ServeFiles(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
filePath := filepath.Join(".", r.URL.Path)
file, err := os.Open(filePath)
if err != nil {
log.Println(err)
http.Error(w, "no such file", http.StatusNotFound)
return
}
defer file.Close()
fileStat, err := os.Stat(filePath)
if err != nil {
log.Println(err)
http.Error(w, "unable to get file stat", http.StatusInternalServerError)
}
_, filename := path.Split(filePath)
t := fileStat.ModTime()
http.ServeContent(w, r, filename, t, file)
}
func (app App) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { func (app App) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
playlists, err := app.GetPlaylists() playlists, err := app.GetPlaylists()
if err != nil { if err != nil {

View File

@ -1,6 +1,29 @@
import ReconnectingWebSocket from 'reconnecting-websocket'; import ReconnectingWebSocket from 'reconnecting-websocket';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
const DND_DELAY = 300;
const addInteractHandler = (source, handler) => {
source.addEventListener("click", e => {
console.log("click", e);
handler(e, false);
});
let touchStart;
source.addEventListener("touchstart", e => {
console.log("touch start", touchStart, e.timeStamp, e);
touchStart = e.timeStamp;
}, {passive: true})
source.addEventListener("touchend", e => {
console.log("touch end", touchStart, e);
console.log(e.timeStamp - touchStart)
if ((e.timeStamp - touchStart) < DND_DELAY) {
handler(e, true);
}
}, {passive: true});
}
window.onload = function () { window.onload = function () {
const ws = new ReconnectingWebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/ws"); const ws = new ReconnectingWebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/ws");
@ -13,19 +36,22 @@ window.onload = function () {
const time = document.querySelector("#time") const time = document.querySelector("#time")
const waiting = document.querySelector("#waiting") const waiting = document.querySelector("#waiting")
document.querySelector("input#next").addEventListener("click", (e) => { addInteractHandler(
document.querySelector("input#next"), (e) => {
ws.send(JSON.stringify({ ws.send(JSON.stringify({
"event": "next" "event": "next"
})) }))
}) })
document.querySelector("input#prev").addEventListener("click", (e) => { addInteractHandler(
document.querySelector("input#prev"), (e) => {
ws.send(JSON.stringify({ ws.send(JSON.stringify({
"event": "prev" "event": "prev"
})) }))
}) })
Sortable.create(items, { Sortable.create(items, {
delay: DND_DELAY,
delayOnTouchOnly: true, delayOnTouchOnly: true,
group: "dndmusicbot-playlists", group: "dndmusicbot-playlists",
filter: ".locked", filter: ".locked",
@ -48,6 +74,7 @@ window.onload = function () {
}) })
Sortable.create(amb, { Sortable.create(amb, {
delay: DND_DELAY,
delayOnTouchOnly: true, delayOnTouchOnly: true,
group: "dndmusicbot-ambiance", group: "dndmusicbot-ambiance",
filter: ".locked", filter: ".locked",
@ -127,8 +154,8 @@ window.onload = function () {
} }
} }
document.querySelector("#addambiance").addEventListener("click", (e) => { addInteractHandler(document.querySelector("#addambiance"), (e, isTouch) => {
e.preventDefault() isTouch && e.preventDefault()
//output.innerText = "" //output.innerText = ""
var title = document.querySelector("#inputambiance > input[name='title']") var title = document.querySelector("#inputambiance > input[name='title']")
@ -147,8 +174,8 @@ window.onload = function () {
})) }))
}) })
submit.addEventListener("click", (e) => { addInteractHandler(submit, (e, isTouch) => {
e.preventDefault() isTouch && e.preventDefault()
//output.innerText = "" //output.innerText = ""
var title = document.querySelector("#inputplaylist > input[name='title']") var title = document.querySelector("#inputplaylist > input[name='title']")
@ -170,8 +197,8 @@ window.onload = function () {
url.innerText = "" url.innerText = ""
}) })
document.querySelectorAll("#items .item").forEach(item => item.addEventListener("click", (e) => { document.querySelectorAll("#items .item").forEach(item => addInteractHandler(item, (e, isTouch) => {
e.preventDefault() isTouch && e.preventDefault()
e.target.parentElement.style.pointerEvents = 'none' e.target.parentElement.style.pointerEvents = 'none'
const disableui = setTimeout((t) => { const disableui = setTimeout((t) => {
t.style.pointerEvents = 'auto' t.style.pointerEvents = 'auto'
@ -184,8 +211,8 @@ window.onload = function () {
})) }))
})); }));
document.querySelectorAll("#ambiance .item").forEach(item => item.addEventListener("click", (e) => { document.querySelectorAll("#ambiance .item").forEach(item => addInteractHandler(item, (e, isTouch) => {
e.preventDefault() isTouch && e.preventDefault()
e.target.parentElement.style.pointerEvents = 'none' e.target.parentElement.style.pointerEvents = 'none'
const disableui = setTimeout((t) => { const disableui = setTimeout((t) => {
t.style.pointerEvents = 'auto' t.style.pointerEvents = 'auto'
@ -205,8 +232,8 @@ function addPlaylist(payload) {
newdiv.className = "item" newdiv.className = "item"
newdiv.dataset.id = payload.url newdiv.dataset.id = payload.url
newdiv.innerText = payload.title newdiv.innerText = payload.title
newdiv.addEventListener("click", (e) => { addInteractHandler(newdiv, (e, isTouch) => {
e.preventDefault() isTouch && e.preventDefault()
var id = e.target.dataset.id var id = e.target.dataset.id
ws.send(JSON.stringify({ ws.send(JSON.stringify({

View File

@ -74,6 +74,6 @@
</div> </div>
</div> </div>
</div> </div>
<script src="/js/script.js"></script> <script src="/public/script.js"></script>
</body> </body>
</html> </html>

View File

@ -150,6 +150,7 @@ func (app App) Playlist(playlist string) ([]string, error) {
if pageToken == "" { if pageToken == "" {
break break
} }
call.PageToken(pageToken)
} }
return list, nil return list, nil
} }