Personal presentation timer
This commit is contained in:
8
main.go
8
main.go
@@ -65,6 +65,7 @@ type client struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Admin bool `json:"admin"`
|
Admin bool `json:"admin"`
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
|
ActiveStart int64 `json:"active_start"`
|
||||||
|
|
||||||
clientId string
|
clientId string
|
||||||
room *room
|
room *room
|
||||||
@@ -84,6 +85,7 @@ type adminEvent struct {
|
|||||||
|
|
||||||
type standardEvent struct {
|
type standardEvent struct {
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
|
ActiveStart int64 `json:"active_start"`
|
||||||
TimerStart int64 `json:"timer_start"`
|
TimerStart int64 `json:"timer_start"`
|
||||||
AdminSecret string `json:"admin_secret"`
|
AdminSecret string `json:"admin_secret"`
|
||||||
}
|
}
|
||||||
@@ -223,6 +225,11 @@ func active(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.Active = req.Active
|
c.Active = req.Active
|
||||||
|
if c.Active {
|
||||||
|
c.ActiveStart = time.Now().Unix()
|
||||||
|
} else {
|
||||||
|
c.ActiveStart = 0
|
||||||
|
}
|
||||||
c.update()
|
c.update()
|
||||||
rm.sendAdminEvent(&adminEvent{
|
rm.sendAdminEvent(&adminEvent{
|
||||||
Client: c,
|
Client: c,
|
||||||
@@ -467,6 +474,7 @@ func (c *client) update() {
|
|||||||
e := &event{
|
e := &event{
|
||||||
StandardEvent: &standardEvent{
|
StandardEvent: &standardEvent{
|
||||||
Active: c.Active,
|
Active: c.Active,
|
||||||
|
ActiveStart: c.ActiveStart,
|
||||||
TimerStart: c.room.timerStart.Unix(),
|
TimerStart: c.room.timerStart.Unix(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,9 +79,13 @@ tfoot tr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
|
color: var(--highlight-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
color: var(--highlight-color);
|
}
|
||||||
|
|
||||||
|
.users tbody tr td:nth-child(2) {
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.github {
|
.github {
|
||||||
|
|||||||
@@ -104,18 +104,22 @@ function renderControls(roomId, clientId, adminSecret, prnt, es) {
|
|||||||
}
|
}
|
||||||
function renderTimers(roomId, adminSecret, prnt, es) {
|
function renderTimers(roomId, adminSecret, prnt, es) {
|
||||||
let overallStart = null;
|
let overallStart = null;
|
||||||
|
let meStart = null;
|
||||||
es.addEventListener("message", (e) => {
|
es.addEventListener("message", (e) => {
|
||||||
const event = JSON.parse(e.data);
|
const event = JSON.parse(e.data);
|
||||||
if (!event.standard_event) {
|
if (!event.standard_event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
overallStart = parseInt(event.standard_event.timer_start || "0", 10) || null;
|
overallStart = parseInt(event.standard_event.timer_start || "0", 10) || null;
|
||||||
|
meStart = parseInt(event.standard_event.active_start || "0", 10) || null;
|
||||||
});
|
});
|
||||||
const width = 10;
|
const width = 10;
|
||||||
const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0"));
|
const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0"));
|
||||||
const clock = create(clockDiv, "span");
|
const clock = create(clockDiv, "span");
|
||||||
const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0"));
|
const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0"));
|
||||||
const overall = create(overallDiv, "span");
|
const overall = create(overallDiv, "span");
|
||||||
|
const meDiv = create(prnt, "div", "Me: ".padStart(width, "\u00a0"));
|
||||||
|
const me = create(meDiv, "span");
|
||||||
if (adminSecret) {
|
if (adminSecret) {
|
||||||
const reset = create(overallDiv, "span", "↺", ["action"]);
|
const reset = create(overallDiv, "span", "↺", ["action"]);
|
||||||
reset.addEventListener("click", () => {
|
reset.addEventListener("click", () => {
|
||||||
@@ -142,6 +146,13 @@ function renderTimers(roomId, adminSecret, prnt, es) {
|
|||||||
else {
|
else {
|
||||||
overall.innerText = "";
|
overall.innerText = "";
|
||||||
}
|
}
|
||||||
|
if (meStart) {
|
||||||
|
const d = Math.trunc(now.getTime() / 1000 - meStart);
|
||||||
|
me.innerText = `${Math.trunc(d / 3600).toString().padStart(2, "0")}h${Math.trunc(d % 3600 / 60).toString().padStart(2, "0")}m${Math.trunc(d % 60).toString().padStart(2, "0")}s`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
me.innerText = "";
|
||||||
|
}
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
function renderAdmin(roomId, adminSecret, prnt, es) {
|
function renderAdmin(roomId, adminSecret, prnt, es) {
|
||||||
@@ -149,10 +160,15 @@ function renderAdmin(roomId, adminSecret, prnt, es) {
|
|||||||
const head = create(table, "thead");
|
const head = create(table, "thead");
|
||||||
const head1 = create(head, "tr");
|
const head1 = create(head, "tr");
|
||||||
create(head1, "th", "Name");
|
create(head1, "th", "Name");
|
||||||
|
create(head1, "th", "Active Time");
|
||||||
create(head1, "th", "👑");
|
create(head1, "th", "👑");
|
||||||
create(head1, "th", "👆");
|
create(head1, "th", "👆");
|
||||||
const body = create(table, "tbody");
|
const body = create(table, "tbody");
|
||||||
const rows = new Map();
|
const rows = new Map();
|
||||||
|
es.addEventListener("open", () => {
|
||||||
|
rows.clear();
|
||||||
|
body.innerHTML = "";
|
||||||
|
});
|
||||||
es.addEventListener("message", (e) => {
|
es.addEventListener("message", (e) => {
|
||||||
const event = JSON.parse(e.data);
|
const event = JSON.parse(e.data);
|
||||||
if (!event.admin_event) {
|
if (!event.admin_event) {
|
||||||
@@ -169,6 +185,7 @@ function renderAdmin(roomId, adminSecret, prnt, es) {
|
|||||||
}
|
}
|
||||||
row = document.createElement("tr");
|
row = document.createElement("tr");
|
||||||
row.dataset.name = client.name;
|
row.dataset.name = client.name;
|
||||||
|
row.dataset.activeStart = client.active_start;
|
||||||
let before = null;
|
let before = null;
|
||||||
for (const iter of body.children) {
|
for (const iter of body.children) {
|
||||||
const iterRow = iter;
|
const iterRow = iter;
|
||||||
@@ -179,6 +196,7 @@ function renderAdmin(roomId, adminSecret, prnt, es) {
|
|||||||
}
|
}
|
||||||
body.insertBefore(row, before);
|
body.insertBefore(row, before);
|
||||||
create(row, "td", client.name);
|
create(row, "td", client.name);
|
||||||
|
create(row, "td");
|
||||||
const adminCell = create(row, "td", "👑", client.admin ? ["admin", "enable"] : ["admin"]);
|
const adminCell = create(row, "td", "👑", client.admin ? ["admin", "enable"] : ["admin"]);
|
||||||
adminCell.addEventListener("click", () => {
|
adminCell.addEventListener("click", () => {
|
||||||
if (!client.admin) {
|
if (!client.admin) {
|
||||||
@@ -194,6 +212,17 @@ function renderAdmin(roomId, adminSecret, prnt, es) {
|
|||||||
});
|
});
|
||||||
rows.set(client.public_client_id, row);
|
rows.set(client.public_client_id, row);
|
||||||
});
|
});
|
||||||
|
setInterval(() => {
|
||||||
|
const now = new Date();
|
||||||
|
for (const row of rows.values()) {
|
||||||
|
const cell = row.children[1];
|
||||||
|
const as = parseInt(row.dataset.activeStart || "0", 10) || null;
|
||||||
|
if (as) {
|
||||||
|
const d = Math.trunc(now.getTime() / 1000 - as);
|
||||||
|
cell.innerText = `${Math.trunc(d / 3600).toString().padStart(2, "0")}h${Math.trunc(d % 3600 / 60).toString().padStart(2, "0")}m${Math.trunc(d % 60).toString().padStart(2, "0")}s`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
}
|
}
|
||||||
function active(roomId, adminSecret, publicClientId, val) {
|
function active(roomId, adminSecret, publicClientId, val) {
|
||||||
const req = {
|
const req = {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ interface Event {
|
|||||||
interface StandardEvent {
|
interface StandardEvent {
|
||||||
timer_start?: string;
|
timer_start?: string;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
active_start?: string;
|
||||||
admin_secret?: string;
|
admin_secret?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ interface Client {
|
|||||||
name: string;
|
name: string;
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
active_start: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
@@ -191,7 +193,8 @@ function renderControls(roomId: string, clientId: string, adminSecret: string |
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElement, es: EventSource) {
|
function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElement, es: EventSource) {
|
||||||
let overallStart: number | null = null;
|
let overallStart: number | null = null;
|
||||||
|
let meStart: number | null = null;
|
||||||
|
|
||||||
es.addEventListener("message", (e) => {
|
es.addEventListener("message", (e) => {
|
||||||
const event = JSON.parse(e.data) as Event;
|
const event = JSON.parse(e.data) as Event;
|
||||||
@@ -201,6 +204,7 @@ function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElem
|
|||||||
}
|
}
|
||||||
|
|
||||||
overallStart = parseInt(event.standard_event.timer_start || "0", 10) || null;
|
overallStart = parseInt(event.standard_event.timer_start || "0", 10) || null;
|
||||||
|
meStart = parseInt(event.standard_event.active_start || "0", 10) || null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const width = 10;
|
const width = 10;
|
||||||
@@ -211,6 +215,9 @@ function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElem
|
|||||||
const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0"));
|
const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0"));
|
||||||
const overall = create(overallDiv, "span");
|
const overall = create(overallDiv, "span");
|
||||||
|
|
||||||
|
const meDiv = create(prnt, "div", "Me: ".padStart(width, "\u00a0"));
|
||||||
|
const me = create(meDiv, "span");
|
||||||
|
|
||||||
if (adminSecret) {
|
if (adminSecret) {
|
||||||
const reset = create(overallDiv, "span", "↺", ["action"]);
|
const reset = create(overallDiv, "span", "↺", ["action"]);
|
||||||
reset.addEventListener("click", () => {
|
reset.addEventListener("click", () => {
|
||||||
@@ -239,6 +246,13 @@ function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElem
|
|||||||
} else {
|
} else {
|
||||||
overall.innerText = "";
|
overall.innerText = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meStart) {
|
||||||
|
const d = Math.trunc(now.getTime() / 1000 - meStart);
|
||||||
|
me.innerText = `${Math.trunc(d / 3600).toString().padStart(2, "0")}h${Math.trunc(d % 3600 / 60).toString().padStart(2, "0")}m${Math.trunc(d % 60).toString().padStart(2, "0")}s`;
|
||||||
|
} else {
|
||||||
|
me.innerText = "";
|
||||||
|
}
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +261,7 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
|
|||||||
const head = create(table, "thead");
|
const head = create(table, "thead");
|
||||||
const head1 = create(head, "tr");
|
const head1 = create(head, "tr");
|
||||||
create(head1, "th", "Name");
|
create(head1, "th", "Name");
|
||||||
|
create(head1, "th", "Active Time");
|
||||||
create(head1, "th", "👑");
|
create(head1, "th", "👑");
|
||||||
create(head1, "th", "👆");
|
create(head1, "th", "👆");
|
||||||
|
|
||||||
@@ -254,6 +269,11 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
|
|||||||
|
|
||||||
const rows: Map<string, HTMLTableRowElement> = new Map();
|
const rows: Map<string, HTMLTableRowElement> = new Map();
|
||||||
|
|
||||||
|
es.addEventListener("open", () => {
|
||||||
|
rows.clear();
|
||||||
|
body.innerHTML = "";
|
||||||
|
});
|
||||||
|
|
||||||
es.addEventListener("message", (e) => {
|
es.addEventListener("message", (e) => {
|
||||||
const event = JSON.parse(e.data) as Event;
|
const event = JSON.parse(e.data) as Event;
|
||||||
|
|
||||||
@@ -275,6 +295,7 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
|
|||||||
|
|
||||||
row = document.createElement("tr") as HTMLTableRowElement;
|
row = document.createElement("tr") as HTMLTableRowElement;
|
||||||
row.dataset.name = client.name;
|
row.dataset.name = client.name;
|
||||||
|
row.dataset.activeStart = client.active_start;
|
||||||
|
|
||||||
let before = null;
|
let before = null;
|
||||||
for (const iter of body.children) {
|
for (const iter of body.children) {
|
||||||
@@ -287,6 +308,7 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
|
|||||||
body.insertBefore(row, before);
|
body.insertBefore(row, before);
|
||||||
|
|
||||||
create(row, "td", client.name);
|
create(row, "td", client.name);
|
||||||
|
create(row, "td");
|
||||||
|
|
||||||
const adminCell = create(row, "td", "👑", client.admin ? ["admin", "enable"] : ["admin"]) as HTMLTableCellElement;
|
const adminCell = create(row, "td", "👑", client.admin ? ["admin", "enable"] : ["admin"]) as HTMLTableCellElement;
|
||||||
adminCell.addEventListener("click", () => {
|
adminCell.addEventListener("click", () => {
|
||||||
@@ -305,6 +327,19 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
|
|||||||
|
|
||||||
rows.set(client.public_client_id, row);
|
rows.set(client.public_client_id, row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
for (const row of rows.values()) {
|
||||||
|
const cell = row.children[1] as HTMLTableCellElement;
|
||||||
|
const as = parseInt(row.dataset.activeStart || "0", 10) || null;
|
||||||
|
if (as) {
|
||||||
|
const d = Math.trunc(now.getTime() / 1000 - as);
|
||||||
|
cell.innerText = `${Math.trunc(d / 3600).toString().padStart(2, "0")}h${Math.trunc(d % 3600 / 60).toString().padStart(2, "0")}m${Math.trunc(d % 60).toString().padStart(2, "0")}s`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
function active(roomId: string, adminSecret: string, publicClientId: string, val: boolean) {
|
function active(roomId: string, adminSecret: string, publicClientId: string, val: boolean) {
|
||||||
|
|||||||
Reference in New Issue
Block a user