Add toggle for ghost turning
This commit is contained in:
parent
00da6db08d
commit
f0c09b2e1b
|
|
@ -257,6 +257,7 @@
|
||||||
<button class="btn btn-secondary" id="bypassTurnBtn"><i class="fa-solid fa-forward"></i> <span id="bypassTurnBtnText"></span></button>
|
<button class="btn btn-secondary" id="bypassTurnBtn"><i class="fa-solid fa-forward"></i> <span id="bypassTurnBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="endTurnBtn"><i class="fa-solid fa-ban"></i> <span id="endTurnBtnText"></span></button>
|
<button class="btn btn-secondary" id="endTurnBtn"><i class="fa-solid fa-ban"></i> <span id="endTurnBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="indefTurnBtn"><i class="fa-solid fa-infinity"></i> <span id="indefTurnBtnText"></span></button>
|
<button class="btn btn-secondary" id="indefTurnBtn"><i class="fa-solid fa-infinity"></i> <span id="indefTurnBtnText"></span></button>
|
||||||
|
<button class="btn btn-secondary" id="ghostTurnBtn"><i class="fa-solid fa-ghost"></i> <span id="ghostTurnBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="qemuMonitorBtn" data-bs-toggle="modal" data-bs-target="#qemuMonitorModal"><i class="fa-solid fa-terminal"></i> <span id="qemuMonitorBtnText"></span></button>
|
<button class="btn btn-secondary" id="qemuMonitorBtn" data-bs-toggle="modal" data-bs-target="#qemuMonitorModal"><i class="fa-solid fa-terminal"></i> <span id="qemuMonitorBtnText"></span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ const fallbackLanguage : Language = {
|
||||||
"kAdminVMButtons_ClearTurnQueue": "Clear Turn Queue",
|
"kAdminVMButtons_ClearTurnQueue": "Clear Turn Queue",
|
||||||
"kAdminVMButtons_BypassTurn": "Bypass Turn",
|
"kAdminVMButtons_BypassTurn": "Bypass Turn",
|
||||||
"kAdminVMButtons_IndefiniteTurn": "Indefinite Turn",
|
"kAdminVMButtons_IndefiniteTurn": "Indefinite Turn",
|
||||||
|
"kAdminVMButtons_GhostTurnOn": "Ghost Turn (On)",
|
||||||
|
"kAdminVMButtons_GhostTurnOff": "Ghost Turn (Off)",
|
||||||
|
|
||||||
"kAdminVMButtons_Ban": "Ban",
|
"kAdminVMButtons_Ban": "Ban",
|
||||||
"kAdminVMButtons_Kick": "Kick",
|
"kAdminVMButtons_Kick": "Kick",
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ export enum I18nStringKey {
|
||||||
kAdminVMButtons_ClearTurnQueue = 'kAdminVMButtons_ClearTurnQueue',
|
kAdminVMButtons_ClearTurnQueue = 'kAdminVMButtons_ClearTurnQueue',
|
||||||
kAdminVMButtons_BypassTurn = 'kAdminVMButtons_BypassTurn',
|
kAdminVMButtons_BypassTurn = 'kAdminVMButtons_BypassTurn',
|
||||||
kAdminVMButtons_IndefiniteTurn = 'kAdminVMButtons_IndefiniteTurn',
|
kAdminVMButtons_IndefiniteTurn = 'kAdminVMButtons_IndefiniteTurn',
|
||||||
|
kAdminVMButtons_GhostTurnOn = 'kAdminVMButtons_GhostTurnOn',
|
||||||
|
kAdminVMButtons_GhostTurnOff = 'kAdminVMButtons_GhostTurnOff',
|
||||||
|
|
||||||
kAdminVMButtons_Ban = 'kAdminVMButtons_Ban',
|
kAdminVMButtons_Ban = 'kAdminVMButtons_Ban',
|
||||||
kAdminVMButtons_Kick = 'kAdminVMButtons_Kick',
|
kAdminVMButtons_Kick = 'kAdminVMButtons_Kick',
|
||||||
|
|
@ -272,6 +274,7 @@ export class I18n {
|
||||||
clearQueueBtnText: I18nStringKey.kAdminVMButtons_ClearTurnQueue,
|
clearQueueBtnText: I18nStringKey.kAdminVMButtons_ClearTurnQueue,
|
||||||
bypassTurnBtnText: I18nStringKey.kAdminVMButtons_BypassTurn,
|
bypassTurnBtnText: I18nStringKey.kAdminVMButtons_BypassTurn,
|
||||||
indefTurnBtnText: I18nStringKey.kAdminVMButtons_IndefiniteTurn,
|
indefTurnBtnText: I18nStringKey.kAdminVMButtons_IndefiniteTurn,
|
||||||
|
ghostTurnBtnText: I18nStringKey.kAdminVMButtons_GhostTurnOff,
|
||||||
|
|
||||||
// Account modal
|
// Account modal
|
||||||
accountLoginUsernameLabel: I18nStringKey.kGeneric_Username,
|
accountLoginUsernameLabel: I18nStringKey.kGeneric_Username,
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ const elements = {
|
||||||
forceVoteYesBtn: document.getElementById('forceVoteYesBtn') as HTMLButtonElement,
|
forceVoteYesBtn: document.getElementById('forceVoteYesBtn') as HTMLButtonElement,
|
||||||
forceVoteNoBtn: document.getElementById('forceVoteNoBtn') as HTMLButtonElement,
|
forceVoteNoBtn: document.getElementById('forceVoteNoBtn') as HTMLButtonElement,
|
||||||
indefTurnBtn: document.getElementById('indefTurnBtn') as HTMLButtonElement,
|
indefTurnBtn: document.getElementById('indefTurnBtn') as HTMLButtonElement,
|
||||||
|
ghostTurnBtn: document.getElementById('ghostTurnBtn') as HTMLButtonElement,
|
||||||
|
ghostTurnBtnText: document.getElementById('ghostTurnBtnText') as HTMLSpanElement,
|
||||||
qemuMonitorInput: document.getElementById('qemuMonitorInput') as HTMLInputElement,
|
qemuMonitorInput: document.getElementById('qemuMonitorInput') as HTMLInputElement,
|
||||||
qemuMonitorSendBtn: document.getElementById('qemuMonitorSendBtn') as HTMLButtonElement,
|
qemuMonitorSendBtn: document.getElementById('qemuMonitorSendBtn') as HTMLButtonElement,
|
||||||
qemuMonitorOutput: document.getElementById('qemuMonitorOutput') as HTMLTextAreaElement,
|
qemuMonitorOutput: document.getElementById('qemuMonitorOutput') as HTMLTextAreaElement,
|
||||||
|
|
@ -482,6 +484,7 @@ function closeVM() {
|
||||||
elements.clearQueueBtn.style.display = 'none';
|
elements.clearQueueBtn.style.display = 'none';
|
||||||
elements.qemuMonitorBtn.style.display = 'none';
|
elements.qemuMonitorBtn.style.display = 'none';
|
||||||
elements.indefTurnBtn.style.display = 'none';
|
elements.indefTurnBtn.style.display = 'none';
|
||||||
|
elements.ghostTurnBtn.style.display = 'none';
|
||||||
elements.xssCheckboxContainer.style.display = 'none';
|
elements.xssCheckboxContainer.style.display = 'none';
|
||||||
elements.forceVotePanel.style.display = 'none';
|
elements.forceVotePanel.style.display = 'none';
|
||||||
elements.voteResetPanel.style.display = 'none';
|
elements.voteResetPanel.style.display = 'none';
|
||||||
|
|
@ -813,6 +816,7 @@ function onLogin(_rank: Rank, _perms: Permissions) {
|
||||||
if (_rank === Rank.Admin) {
|
if (_rank === Rank.Admin) {
|
||||||
elements.qemuMonitorBtn.style.display = 'inline-block';
|
elements.qemuMonitorBtn.style.display = 'inline-block';
|
||||||
elements.indefTurnBtn.style.display = 'inline-block';
|
elements.indefTurnBtn.style.display = 'inline-block';
|
||||||
|
elements.ghostTurnBtn.style.display = 'inline-block';
|
||||||
}
|
}
|
||||||
if (_perms.xss) elements.xssCheckboxContainer.style.display = 'inline-block';
|
if (_perms.xss) elements.xssCheckboxContainer.style.display = 'inline-block';
|
||||||
if (_perms.forcevote) elements.forceVotePanel.style.display = 'block';
|
if (_perms.forcevote) elements.forceVotePanel.style.display = 'block';
|
||||||
|
|
@ -876,6 +880,15 @@ elements.forceVoteNoBtn.addEventListener('click', () => VM?.forceVote(false));
|
||||||
elements.forceVoteYesBtn.addEventListener('click', () => VM?.forceVote(true));
|
elements.forceVoteYesBtn.addEventListener('click', () => VM?.forceVote(true));
|
||||||
elements.indefTurnBtn.addEventListener('click', () => VM?.indefiniteTurn());
|
elements.indefTurnBtn.addEventListener('click', () => VM?.indefiniteTurn());
|
||||||
|
|
||||||
|
|
||||||
|
elements.ghostTurnBtn.addEventListener('click', () => {
|
||||||
|
w.collabvm.ghostTurn = !w.collabvm.ghostTurn;
|
||||||
|
if (w.collabvm.ghostTurn)
|
||||||
|
elements.ghostTurnBtnText.innerText = TheI18n.GetString(I18nStringKey.kAdminVMButtons_GhostTurnOn);
|
||||||
|
else
|
||||||
|
elements.ghostTurnBtnText.innerText = TheI18n.GetString(I18nStringKey.kAdminVMButtons_GhostTurnOff);
|
||||||
|
});
|
||||||
|
|
||||||
async function sendQEMUCommand() {
|
async function sendQEMUCommand() {
|
||||||
if (!elements.qemuMonitorInput.value) return;
|
if (!elements.qemuMonitorInput.value) return;
|
||||||
let cmd = elements.qemuMonitorInput.value;
|
let cmd = elements.qemuMonitorInput.value;
|
||||||
|
|
@ -1212,7 +1225,8 @@ w.collabvm = {
|
||||||
closeVM: closeVM,
|
closeVM: closeVM,
|
||||||
loadList: loadList,
|
loadList: loadList,
|
||||||
multicollab: multicollab,
|
multicollab: multicollab,
|
||||||
getVM: () => VM
|
getVM: () => VM,
|
||||||
|
ghostTurn: false,
|
||||||
};
|
};
|
||||||
// Multicollab will stay in the global scope for backwards compatibility
|
// Multicollab will stay in the global scope for backwards compatibility
|
||||||
w.multicollab = multicollab;
|
w.multicollab = multicollab;
|
||||||
|
|
@ -1276,6 +1290,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
if (darkTheme) elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_LightMode);
|
if (darkTheme) elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_LightMode);
|
||||||
else elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_DarkMode);
|
else elements.toggleThemeBtnText.innerHTML = TheI18n.GetString(I18nStringKey.kSiteButtons_DarkMode);
|
||||||
|
|
||||||
|
if (w.collabvm.ghostTurn)
|
||||||
|
elements.ghostTurnBtnText.innerText = TheI18n.GetString(I18nStringKey.kAdminVMButtons_GhostTurnOn);
|
||||||
|
else
|
||||||
|
elements.ghostTurnBtnText.innerText = TheI18n.GetString(I18nStringKey.kAdminVMButtons_GhostTurnOff);
|
||||||
});
|
});
|
||||||
// Load theme
|
// Load theme
|
||||||
var _darktheme : boolean;
|
var _darktheme : boolean;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import GetKeysym from '../keyboard.js';
|
||||||
import VoteStatus from './VoteStatus.js';
|
import VoteStatus from './VoteStatus.js';
|
||||||
import MuteState from './MuteState.js';
|
import MuteState from './MuteState.js';
|
||||||
import { StringLike } from '../StringLike.js';
|
import { StringLike } from '../StringLike.js';
|
||||||
|
const w = window as any;
|
||||||
|
|
||||||
export interface CollabVMClientEvents {
|
export interface CollabVMClientEvents {
|
||||||
//open: () => void;
|
//open: () => void;
|
||||||
|
|
@ -98,7 +99,7 @@ export default class CollabVMClient {
|
||||||
this.canvas.addEventListener(
|
this.canvas.addEventListener(
|
||||||
'mousedown',
|
'mousedown',
|
||||||
(e: MouseEvent) => {
|
(e: MouseEvent) => {
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
this.mouse.initFromMouseEvent(e);
|
this.mouse.initFromMouseEvent(e);
|
||||||
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
||||||
},
|
},
|
||||||
|
|
@ -110,7 +111,7 @@ export default class CollabVMClient {
|
||||||
this.canvas.addEventListener(
|
this.canvas.addEventListener(
|
||||||
'mouseup',
|
'mouseup',
|
||||||
(e: MouseEvent) => {
|
(e: MouseEvent) => {
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
this.mouse.initFromMouseEvent(e);
|
this.mouse.initFromMouseEvent(e);
|
||||||
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
||||||
},
|
},
|
||||||
|
|
@ -122,7 +123,7 @@ export default class CollabVMClient {
|
||||||
this.canvas.addEventListener(
|
this.canvas.addEventListener(
|
||||||
'mousemove',
|
'mousemove',
|
||||||
(e: MouseEvent) => {
|
(e: MouseEvent) => {
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
this.mouse.initFromMouseEvent(e);
|
this.mouse.initFromMouseEvent(e);
|
||||||
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
||||||
},
|
},
|
||||||
|
|
@ -135,7 +136,7 @@ export default class CollabVMClient {
|
||||||
'keydown',
|
'keydown',
|
||||||
(e: KeyboardEvent) => {
|
(e: KeyboardEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
let keysym = GetKeysym(e.keyCode, e.key, e.location);
|
let keysym = GetKeysym(e.keyCode, e.key, e.location);
|
||||||
if (keysym === null) return;
|
if (keysym === null) return;
|
||||||
this.key(keysym, true);
|
this.key(keysym, true);
|
||||||
|
|
@ -149,7 +150,7 @@ export default class CollabVMClient {
|
||||||
'keyup',
|
'keyup',
|
||||||
(e: KeyboardEvent) => {
|
(e: KeyboardEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
let keysym = GetKeysym(e.keyCode, e.key, e.location);
|
let keysym = GetKeysym(e.keyCode, e.key, e.location);
|
||||||
if (keysym === null) return;
|
if (keysym === null) return;
|
||||||
this.key(keysym, false);
|
this.key(keysym, false);
|
||||||
|
|
@ -163,7 +164,7 @@ export default class CollabVMClient {
|
||||||
'wheel',
|
'wheel',
|
||||||
(ev: WheelEvent) => {
|
(ev: WheelEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (this.users.find((u) => u.username === this.username)?.turn === -1 && this.rank !== Rank.Admin) return;
|
if (!this.shouldSendInput()) return;
|
||||||
this.mouse.initFromWheelEvent(ev);
|
this.mouse.initFromWheelEvent(ev);
|
||||||
|
|
||||||
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
this.sendmouse(this.mouse.x, this.mouse.y, this.mouse.makeMask());
|
||||||
|
|
@ -677,6 +678,10 @@ export default class CollabVMClient {
|
||||||
return this.internalEmitter.on(event, callback);
|
return this.internalEmitter.on(event, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private shouldSendInput() {
|
||||||
|
return this.users.find(u => u.username === this.username)?.turn === 0 || (w.collabvm.ghostTurn && this.rank === Rank.Admin);
|
||||||
|
}
|
||||||
|
|
||||||
on<E extends keyof CollabVMClientEvents>(event: E, callback: CollabVMClientEvents[E]): Unsubscribe {
|
on<E extends keyof CollabVMClientEvents>(event: E, callback: CollabVMClientEvents[E]): Unsubscribe {
|
||||||
let unsub = this.publicEmitter.on(event, callback);
|
let unsub = this.publicEmitter.on(event, callback);
|
||||||
this.unsubscribeCallbacks.push(unsub);
|
this.unsubscribeCallbacks.push(unsub);
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@
|
||||||
"kAdminVMButtons_ClearTurnQueue": "Clear Turn Queue",
|
"kAdminVMButtons_ClearTurnQueue": "Clear Turn Queue",
|
||||||
"kAdminVMButtons_BypassTurn": "Bypass Turn",
|
"kAdminVMButtons_BypassTurn": "Bypass Turn",
|
||||||
"kAdminVMButtons_IndefiniteTurn": "Indefinite Turn",
|
"kAdminVMButtons_IndefiniteTurn": "Indefinite Turn",
|
||||||
|
"kAdminVMButtons_GhostTurnOn": "Ghost Turn (On)",
|
||||||
|
"kAdminVMButtons_GhostTurnOff": "Ghost Turn (Off)",
|
||||||
|
|
||||||
"kAdminVMButtons_Ban": "Ban",
|
"kAdminVMButtons_Ban": "Ban",
|
||||||
"kAdminVMButtons_Kick": "Kick",
|
"kAdminVMButtons_Kick": "Kick",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user