implement vote-to-reset, screenshotting, and fix system messages
This commit is contained in:
parent
659d3baaea
commit
901109a389
|
|
@ -7,6 +7,7 @@ import TurnStatus from "./protocol/TurnStatus.js";
|
|||
import Keyboard from "simple-keyboard";
|
||||
import { OSK_buttonToKeysym } from "./keyboard";
|
||||
import "simple-keyboard/build/css/index.css";
|
||||
import VoteStatus from "./protocol/VoteStatus.js";
|
||||
|
||||
// Elements
|
||||
const w = window as any;
|
||||
|
|
@ -27,7 +28,15 @@ const elements = {
|
|||
turnBtnText: document.getElementById("turnBtnText") as HTMLSpanElement,
|
||||
turnstatus: document.getElementById("turnstatus") as HTMLParagraphElement,
|
||||
osk: window.document.getElementById("oskBtn") as HTMLButtonElement,
|
||||
oskContainer: document.getElementById("osk-container") as HTMLDivElement
|
||||
oskContainer: document.getElementById("osk-container") as HTMLDivElement,
|
||||
screenshotButton: document.getElementById("screenshotButton") as HTMLButtonElement,
|
||||
voteResetButton: document.getElementById("voteResetButton") as HTMLButtonElement,
|
||||
voteResetPanel: document.getElementById("voteResetPanel") as HTMLDivElement,
|
||||
voteYesBtn: document.getElementById("voteYesBtn") as HTMLButtonElement,
|
||||
voteNoBtn: document.getElementById("voteNoBtn") as HTMLButtonElement,
|
||||
voteYesLabel: document.getElementById("voteYesLabel") as HTMLSpanElement,
|
||||
voteNoLabel: document.getElementById("voteNoLabel") as HTMLSpanElement,
|
||||
votetime: document.getElementById("votetime") as HTMLSpanElement,
|
||||
}
|
||||
|
||||
/* Start OSK */
|
||||
|
|
@ -224,8 +233,10 @@ const users : {
|
|||
user : User,
|
||||
element : HTMLTableRowElement
|
||||
}[] = [];
|
||||
var turnInterval : number | undefined = undefined;;
|
||||
var turnInterval : number | undefined = undefined;
|
||||
var voteInterval : number | undefined = undefined;
|
||||
var turnTimer = 0;
|
||||
var voteTimer = 0;
|
||||
|
||||
// Active VM
|
||||
var VM : CollabVMClient | null = null;
|
||||
|
|
@ -294,6 +305,9 @@ function openVM(vm : VM) {
|
|||
}
|
||||
}));
|
||||
listeners.push(VM!.on('turn', status => turnUpdate(status)));
|
||||
listeners.push(VM!.on('vote', (status : VoteStatus) => voteUpdate(status)));
|
||||
listeners.push(VM!.on('voteend', () => voteEnd()));
|
||||
listeners.push(VM!.on('votecd', cd => window.alert(`Please wait ${cd} seconds before starting another vote.`)));
|
||||
listeners.push(VM!.on('close', () => {
|
||||
if (!expectedClose) alert("You have been disconnected from the server");
|
||||
for (var l of listeners) l();
|
||||
|
|
@ -352,7 +366,7 @@ function loadList() {
|
|||
|
||||
function sortVMList() {
|
||||
cards.sort(function(a, b) {
|
||||
return a.getAttribute("data-cvm-node")! > b.getAttribute("data-cvm-node")! ? 1 : -1;
|
||||
return a.children[0].getAttribute("data-cvm-node")! > b.children[0].getAttribute("data-cvm-node")! ? 1 : -1;
|
||||
});
|
||||
elements.vmlist.children[0].innerHTML = "";
|
||||
cards.forEach((c) => elements.vmlist.children[0].appendChild(c));
|
||||
|
|
@ -408,10 +422,10 @@ function chatMessage(username : string, message : string) {
|
|||
eval(curr.text)
|
||||
}
|
||||
});
|
||||
tr.appendChild(td);
|
||||
elements.chatList.appendChild(tr);
|
||||
elements.chatListDiv.scrollTop = elements.chatListDiv.scrollHeight;
|
||||
}
|
||||
tr.appendChild(td);
|
||||
elements.chatList.appendChild(tr);
|
||||
elements.chatListDiv.scrollTop = elements.chatListDiv.scrollHeight;
|
||||
}
|
||||
|
||||
function addUser(user : User) {
|
||||
|
|
@ -504,6 +518,27 @@ function turnUpdate(status : TurnStatus) {
|
|||
sortUserList();
|
||||
}
|
||||
|
||||
function voteUpdate(status : VoteStatus) {
|
||||
clearInterval(voteInterval);
|
||||
elements.voteResetPanel.style.display = "block";
|
||||
elements.voteYesLabel.innerText = status.yesVotes.toString();
|
||||
elements.voteNoLabel.innerText = status.noVotes.toString();
|
||||
voteTimer = Math.floor(status.timeToEnd / 1000);
|
||||
voteInterval = setInterval(() => updateVoteEndTime(), 1000);
|
||||
updateVoteEndTime();
|
||||
}
|
||||
|
||||
function updateVoteEndTime() {
|
||||
voteTimer--;
|
||||
elements.votetime.innerText = voteTimer.toString();
|
||||
if (voteTimer === 0) clearInterval(voteInterval);
|
||||
}
|
||||
|
||||
function voteEnd() {
|
||||
clearInterval(voteInterval);
|
||||
elements.voteResetPanel.style.display = "none";
|
||||
}
|
||||
|
||||
function turnIntervalCb() {
|
||||
turnTimer--;
|
||||
setTurnStatus();
|
||||
|
|
@ -538,6 +573,15 @@ elements.changeUsernameBtn.addEventListener('click', () => {
|
|||
elements.takeTurnBtn.addEventListener('click', () => {
|
||||
VM?.turn(turn === -1);
|
||||
});
|
||||
elements.screenshotButton.addEventListener('click', () => {
|
||||
if (!VM) return;
|
||||
VM.canvas.toBlob(blob => {
|
||||
open(URL.createObjectURL(blob!), '_blank');
|
||||
})
|
||||
});
|
||||
elements.voteResetButton.addEventListener('click', () => VM?.vote(true));
|
||||
elements.voteYesBtn.addEventListener('click', () => VM?.vote(true));
|
||||
elements.voteNoBtn.addEventListener('click', () => VM?.vote(false));
|
||||
|
||||
elements.osk.addEventListener('click', () => elements.oskContainer.classList.toggle('d-none'));
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { Rank } from "./Permissions.js";
|
|||
import TurnStatus from "./TurnStatus.js";
|
||||
import Mouse from "./mouse.js";
|
||||
import GetKeysym from '../keyboard.js';
|
||||
import VoteStatus from "./VoteStatus.js";
|
||||
|
||||
export default class CollabVMClient {
|
||||
// Fields
|
||||
|
|
@ -18,6 +19,7 @@ export default class CollabVMClient {
|
|||
private username : string | null = null;
|
||||
private mouse : Mouse = new Mouse();
|
||||
private rank : Rank = Rank.Unregistered;
|
||||
private voteStatus : VoteStatus | null = null;
|
||||
// events that are used internally and not exposed
|
||||
private emitter;
|
||||
// public events
|
||||
|
|
@ -63,6 +65,7 @@ export default class CollabVMClient {
|
|||
capture: true
|
||||
});
|
||||
this.canvas.addEventListener('keydown', (e : KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
||||
var keysym = GetKeysym(e.keyCode, e.key, e.location);
|
||||
if (keysym === null) return;
|
||||
|
|
@ -71,6 +74,7 @@ export default class CollabVMClient {
|
|||
capture: true
|
||||
});
|
||||
this.canvas.addEventListener('keyup', (e : KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
if (this.users.find(u => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
||||
var keysym = GetKeysym(e.keyCode, e.key, e.location);
|
||||
if (keysym === null) return;
|
||||
|
|
@ -218,6 +222,35 @@ export default class CollabVMClient {
|
|||
} as TurnStatus)
|
||||
break;
|
||||
}
|
||||
case "vote": {
|
||||
switch (msgArr[1]) {
|
||||
case "0":
|
||||
// Vote started
|
||||
case "1":
|
||||
// Vote updated
|
||||
var timeToEnd = parseInt(msgArr[2]);
|
||||
var yesVotes = parseInt(msgArr[3]);
|
||||
var noVotes = parseInt(msgArr[4]);
|
||||
// Some server implementations dont send data for status 0, and some do
|
||||
if (Number.isNaN(timeToEnd) || Number.isNaN(yesVotes) || Number.isNaN(noVotes)) return;
|
||||
this.voteStatus = {
|
||||
timeToEnd: timeToEnd,
|
||||
yesVotes: yesVotes,
|
||||
noVotes: noVotes,
|
||||
};
|
||||
this.publicEmitter.emit('vote', this.voteStatus);
|
||||
break;
|
||||
case "2":
|
||||
// Vote ended
|
||||
this.voteStatus = null;
|
||||
this.publicEmitter.emit('voteend');
|
||||
break;
|
||||
case "3":
|
||||
// Cooldown
|
||||
this.publicEmitter.emit('votecd', parseInt(msgArr[2]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,5 +332,15 @@ export default class CollabVMClient {
|
|||
this.send("key", keysym.toString(), down ? "1" : "0");
|
||||
}
|
||||
|
||||
// Get vote status
|
||||
getVoteStatus() : VoteStatus | null {
|
||||
return this.voteStatus;
|
||||
}
|
||||
|
||||
// Start a vote, or vote
|
||||
vote(vote : boolean) {
|
||||
this.send("vote", vote ? "1" : "0");
|
||||
}
|
||||
|
||||
on = (event : string | number, cb: (...args: any) => void) => this.publicEmitter.on(event, cb);
|
||||
}
|
||||
5
src/ts/protocol/VoteStatus.ts
Normal file
5
src/ts/protocol/VoteStatus.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export default interface VoteStatus {
|
||||
timeToEnd: number;
|
||||
yesVotes: number;
|
||||
noVotes: number;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user