From 82da61bd8649283837382e8b8b675135cccf36cc Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Wed, 25 Nov 2020 22:41:05 +0000 Subject: [PATCH] Add solo button --- main.go | 71 +++++++++++++++++++++++++++++------------------ static/remote.css | 3 +- static/remote.js | 33 ++++++++++++++++++++-- static/remote.ts | 37 ++++++++++++++++++++++-- 4 files changed, 112 insertions(+), 32 deletions(-) diff --git a/main.go b/main.go index 0fa92f7..a3cb1eb 100644 --- a/main.go +++ b/main.go @@ -20,21 +20,22 @@ import ( ) type activeRequest struct { - RoomId string `json:"room_id"` - AdminSecret string `json:"admin_secret"` - ClientId string `json:"client_id"` - Active bool `json:"active"` + RoomId string `json:"room_id"` + AdminSecret string `json:"admin_secret"` + ClientId string `json:"client_id"` + Active bool `json:"active"` + Solo bool `json:"solo"` } type adminRequest struct { - RoomId string `json:"room_id"` - AdminSecret string `json:"admin_secret"` - ClientId string `json:"client_id"` + RoomId string `json:"room_id"` + AdminSecret string `json:"admin_secret"` + ClientId string `json:"client_id"` } type resetRequest struct { - RoomId string `json:"room_id"` - AdminSecret string `json:"admin_secret"` + RoomId string `json:"room_id"` + AdminSecret string `json:"admin_secret"` } type announceRequest struct { @@ -61,11 +62,11 @@ type removeRequest struct { } type client struct { - ClientId string `json:"client_id"` - Name string `json:"name"` - Admin bool `json:"admin"` - Active bool `json:"active"` - ActiveStart int64 `json:"active_start"` + ClientId string `json:"client_id"` + Name string `json:"name"` + Admin bool `json:"admin"` + Active bool `json:"active"` + ActiveStart int64 `json:"active_start"` room *room lastSeen time.Time @@ -94,10 +95,10 @@ type controlEvent struct { } type room struct { - roomId string - timerStart time.Time - clientById map[string]*client - present map[*presentState]bool + roomId string + timerStart time.Time + clientById map[string]*client + present map[*presentState]bool } type presentState struct { @@ -212,7 +213,7 @@ func active(w http.ResponseWriter, r *http.Request) { return } - c.Active = req.Active + c.Active = req.Active || req.Solo if c.Active { c.ActiveStart = time.Now().Unix() } else { @@ -222,6 +223,22 @@ func active(w http.ResponseWriter, r *http.Request) { rm.sendAdminEvent(&adminEvent{ Client: c, }) + + if req.Solo { + for _, iter := range rm.clientById { + if iter == c { + continue + } + if iter.Active { + iter.Active = false + iter.ActiveStart = 0 + iter.update() + rm.sendAdminEvent(&adminEvent{ + Client: iter, + }) + } + } + } } func admin(w http.ResponseWriter, r *http.Request) { @@ -476,9 +493,9 @@ func (c *client) remove() { func (c *client) update() { e := &event{ StandardEvent: &standardEvent{ - Active: c.Active, + Active: c.Active, ActiveStart: c.ActiveStart, - TimerStart: c.room.timerStart.Unix(), + TimerStart: c.room.timerStart.Unix(), }, } if c.Admin { @@ -489,10 +506,10 @@ func (c *client) update() { func newRoom(roomId string) *room { return &room{ - roomId: roomId, - timerStart: time.Now(), - clientById: map[string]*client{}, - present: map[*presentState]bool{}, + roomId: roomId, + timerStart: time.Now(), + clientById: map[string]*client{}, + present: map[*presentState]bool{}, } } @@ -514,8 +531,8 @@ func (rm *room) getClient(clientId string) *client { c := rm.clientById[clientId] if c == nil { c = &client{ - ClientId: clientId, - room: rm, + ClientId: clientId, + room: rm, } rm.clientById[clientId] = c diff --git a/static/remote.css b/static/remote.css index 80d6018..9e3a474 100644 --- a/static/remote.css +++ b/static/remote.css @@ -42,7 +42,8 @@ tfoot tr { } .admin, -.active { +.active, +.solo { cursor: pointer; opacity: 0.3; user-select: none; diff --git a/static/remote.js b/static/remote.js index cf7a742..2dc8b62 100644 --- a/static/remote.js +++ b/static/remote.js @@ -166,6 +166,7 @@ function renderAdmin(roomId, adminSecret, prnt, es) { create(head1, "th", "Active Time"); create(head1, "th", "👑"); create(head1, "th", "👆"); + create(head1, "th", "🌟"); const body = create(table, "tbody"); const rows = new Map(); es.addEventListener("open", () => { @@ -188,6 +189,7 @@ function renderAdmin(roomId, adminSecret, prnt, es) { } row = document.createElement("tr"); row.dataset.name = client.name; + row.dataset.active = client.active ? "active" : ""; row.dataset.activeStart = client.active_start; let before = null; for (const iter of body.children) { @@ -211,9 +213,19 @@ function renderAdmin(roomId, adminSecret, prnt, es) { }); const activeCell = create(row, "td", "👆", client.active ? ["active", "enable"] : ["active"]); activeCell.addEventListener("click", () => { - active(roomId, adminSecret, client.client_id, !activeCell.classList.contains("enable")); + active(roomId, adminSecret, client.client_id, !activeCell.classList.contains("enable"), false); + }); + const soloCell = create(row, "td", "🌟", ["solo"]); + soloCell.addEventListener("click", () => { + if (soloCell.classList.contains("enable")) { + active(roomId, adminSecret, client.client_id, false, false); + } + else { + active(roomId, adminSecret, client.client_id, true, true); + } }); rows.set(client.client_id, row); + setSolo(rows); }); setInterval(() => { const now = new Date(); @@ -227,12 +239,29 @@ function renderAdmin(roomId, adminSecret, prnt, es) { } }, 250); } -function active(roomId, adminSecret, clientId, val) { +function setSolo(rows) { + let activeCount = 0; + for (const row of rows.values()) { + if (row.dataset.active === "active") { + activeCount++; + } + } + for (const row of rows.values()) { + if (activeCount === 1 && row.dataset.active === "active") { + row.children[4].classList.add("enable"); + } + else { + row.children[4].classList.remove("enable"); + } + } +} +function active(roomId, adminSecret, clientId, val, solo) { const req = { room_id: roomId, admin_secret: adminSecret, client_id: clientId, active: val, + solo, }; fetch("api/active", { method: "POST", diff --git a/static/remote.ts b/static/remote.ts index a4b2afd..c282102 100644 --- a/static/remote.ts +++ b/static/remote.ts @@ -3,6 +3,7 @@ interface ActiveRequest { admin_secret: string; client_id: string; active: boolean; + solo: boolean; } interface AdminRequest { @@ -267,6 +268,7 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es: create(head1, "th", "Active Time"); create(head1, "th", "👑"); create(head1, "th", "👆"); + create(head1, "th", "🌟"); const body = create(table, "tbody"); @@ -298,6 +300,7 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es: row = document.createElement("tr") as HTMLTableRowElement; row.dataset.name = client.name; + row.dataset.active = client.active ? "active" : ""; row.dataset.activeStart = client.active_start; let before = null; @@ -325,10 +328,21 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es: const activeCell = create(row, "td", "👆", client.active ? ["active", "enable"] : ["active"]) as HTMLTableCellElement; activeCell.addEventListener("click", () => { - active(roomId, adminSecret, client.client_id, !activeCell.classList.contains("enable")); + active(roomId, adminSecret, client.client_id, !activeCell.classList.contains("enable"), false); + }); + + const soloCell = create(row, "td", "🌟", ["solo"]) as HTMLTableCellElement; + soloCell.addEventListener("click", () => { + if (soloCell.classList.contains("enable")) { + active(roomId, adminSecret, client.client_id, false, false); + } else { + active(roomId, adminSecret, client.client_id, true, true); + } }); rows.set(client.client_id, row); + + setSolo(rows); }); setInterval(() => { @@ -345,12 +359,31 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es: }, 250); } -function active(roomId: string, adminSecret: string, clientId: string, val: boolean) { +function setSolo(rows: Map) { + let activeCount = 0; + + for (const row of rows.values()) { + if (row.dataset.active === "active") { + activeCount++; + } + } + + for (const row of rows.values()) { + if (activeCount === 1 && row.dataset.active === "active") { + row.children[4].classList.add("enable"); + } else { + row.children[4].classList.remove("enable"); + } + } +} + +function active(roomId: string, adminSecret: string, clientId: string, val: boolean, solo: boolean) { const req: ActiveRequest = { room_id: roomId, admin_secret: adminSecret, client_id: clientId, active: val, + solo, }; fetch("api/active", {