Remove "new Promise" hoisting in most cases in main.ts

Not actually needed (and in most cases, the inner lambda was `async` colored anyways, so why not just async color the function itself?)
This commit is contained in:
modeco80 2024-03-12 01:44:04 -04:00
parent 125e6a769d
commit 2661a1a142

View File

@ -240,8 +240,8 @@ function onKeyPress(button: string) {
/* End OSK */ /* End OSK */
var expectedClose = false; let expectedClose = false;
var turn = -1; let turn = -1;
// Listed VMs // Listed VMs
const vms: VM[] = []; const vms: VM[] = [];
const cards: HTMLDivElement[] = []; const cards: HTMLDivElement[] = [];
@ -249,45 +249,50 @@ const users: {
user: User; user: User;
element: HTMLTableRowElement; element: HTMLTableRowElement;
}[] = []; }[] = [];
var turnInterval: number | undefined = undefined; let turnInterval: number | undefined = undefined;
var voteInterval: number | undefined = undefined; let voteInterval: number | undefined = undefined;
var turnTimer = 0; let turnTimer = 0;
var voteTimer = 0; let voteTimer = 0;
var rank: Rank = Rank.Unregistered; let rank: Rank = Rank.Unregistered;
var perms: Permissions = new Permissions(0); let perms: Permissions = new Permissions(0);
const chatsound = new Audio(Config.ChatSound); const chatsound = new Audio(Config.ChatSound);
// Active VM // Active VM
var VM: CollabVMClient | null = null; let VM: CollabVMClient | null = null;
function multicollab(url: string) { async function multicollab(url: string) {
return new Promise<void>(async (res, rej) => {
// Create the client // Create the client
var client = new CollabVMClient(url); let client = new CollabVMClient(url);
// Wait for the client to open // Wait for the client to open
await new Promise<void>((res) => client.on('open', () => res())); await new Promise<void>((res) => client.on('open', () => res()));
// Get the list of VMs // Get the list of VMs
var list = await client.list(); let list = await client.list();
// Get the number of online users // Get the number of online users
var online = client.getUsers().length; let online = client.getUsers().length;
// Close the client // Close the client
client.close(); client.close();
// Add to the list // Add to the list
vms.push(...list); vms.push(...list);
// Add to the DOM // Add to the DOM
for (var vm of list) { for (let vm of list) {
var div = document.createElement('div'); let div = document.createElement('div');
div.classList.add('col-sm-5', 'col-md-3'); div.classList.add('col-sm-5', 'col-md-3');
var card = document.createElement('div'); let card = document.createElement('div');
card.classList.add('card', 'bg-dark', 'text-light'); card.classList.add('card', 'bg-dark', 'text-light');
card.setAttribute('data-cvm-node', vm.id); card.setAttribute('data-cvm-node', vm.id);
card.addEventListener('click', () => openVM(vm)); card.addEventListener('click', async () => {
try {
await openVM(vm);
} catch (e) {
alert((e as Error).message);
}
});
vm.thumbnail.classList.add('card-img-top'); vm.thumbnail.classList.add('card-img-top');
var cardBody = document.createElement('div'); let cardBody = document.createElement('div');
cardBody.classList.add('card-body'); cardBody.classList.add('card-body');
var cardTitle = document.createElement('h5'); let cardTitle = document.createElement('h5');
cardTitle.innerHTML = vm.displayName; cardTitle.innerHTML = vm.displayName;
var usersOnline = document.createElement('span'); let usersOnline = document.createElement('span');
usersOnline.innerHTML = `(<i class="fa-solid fa-users"></i> ${online})`; usersOnline.innerHTML = `(<i class="fa-solid fa-users"></i> ${online})`;
cardBody.appendChild(cardTitle); cardBody.appendChild(cardTitle);
cardBody.appendChild(usersOnline); cardBody.appendChild(usersOnline);
@ -297,12 +302,9 @@ function multicollab(url: string) {
cards.push(div); cards.push(div);
sortVMList(); sortVMList();
} }
res();
});
} }
function openVM(vm: VM) { async function openVM(vm: VM): Promise<void> {
return new Promise<void>(async (res, rej) => {
// If there's an active VM it must be closed before opening another // If there's an active VM it must be closed before opening another
if (VM !== null) return; if (VM !== null) return;
expectedClose = false; expectedClose = false;
@ -313,7 +315,7 @@ function openVM(vm: VM) {
// Register event listeners // Register event listeners
// An array of nanoevent unsubscribe callbacks. These are called when the VM is closed to cleanup nanoevent state. // An array of nanoevent unsubscribe callbacks. These are called when the VM is closed to cleanup nanoevent state.
var unsubscribeCallbacks: Unsubscribe[] = []; let unsubscribeCallbacks: Unsubscribe[] = [];
unsubscribeCallbacks.push(VM!.on('chat', (username, message) => chatMessage(username, message))); unsubscribeCallbacks.push(VM!.on('chat', (username, message) => chatMessage(username, message)));
unsubscribeCallbacks.push(VM!.on('adduser', (user) => addUser(user))); unsubscribeCallbacks.push(VM!.on('adduser', (user) => addUser(user)));
@ -344,23 +346,27 @@ function openVM(vm: VM) {
if (!expectedClose) alert('You have been disconnected from the server'); if (!expectedClose) alert('You have been disconnected from the server');
// Call all the unsubscribe callbacks. // Call all the unsubscribe callbacks.
for (var l of unsubscribeCallbacks) l(); for (let l of unsubscribeCallbacks) l();
unsubscribeCallbacks = []; unsubscribeCallbacks = [];
closeVM(); closeVM();
}) })
); );
// Wait for the client to open // Wait for the client to open
await new Promise<void>((res) => VM!.on('open', () => res())); await new Promise<void>((res) => {
unsubscribeCallbacks.push(VM!.on('open', () => res()));
});
// Connect to node // Connect to node
chatMessage('', `<b>${vm.id}</b><hr>`); chatMessage('', `<b>${vm.id}</b><hr>`);
var username = localStorage.getItem('username'); let username = localStorage.getItem('username');
var connected = await VM.connect(vm.id, username); let connected = await VM.connect(vm.id, username);
elements.adminInputVMID.value = vm.id; elements.adminInputVMID.value = vm.id;
w.VMName = vm.id; w.VMName = vm.id;
if (!connected) { if (!connected) {
VM.close(); // just give up
VM = null; closeVM();
rej('Failed to connect to node'); throw new Error('Failed to connect to node');
} }
// Set the title // Set the title
document.title = vm.id + ' - CollabVM'; document.title = vm.id + ' - CollabVM';
@ -369,10 +375,11 @@ function openVM(vm: VM) {
// Switch to the VM view // Switch to the VM view
elements.vmlist.style.display = 'none'; elements.vmlist.style.display = 'none';
elements.vmview.style.display = 'block'; elements.vmview.style.display = 'block';
}); return;
} }
function closeVM() { function closeVM() {
console.log('closeVM() called');
if (VM === null) return; if (VM === null) return;
expectedClose = true; expectedClose = true;
// Close the VM // Close the VM
@ -410,21 +417,24 @@ function closeVM() {
elements.username.classList.add('text-light'); elements.username.classList.add('text-light');
} }
function loadList() { async function loadList() {
return new Promise<void>(async (res) => { let p = [];
var p = []; for (let url of Config.ServerAddresses) {
for (var url of Config.ServerAddresses) {
p.push(multicollab(url)); p.push(multicollab(url));
} }
await Promise.all(p); await Promise.all(p);
var v = vms.find((v) => v.id === window.location.hash.substring(1));
if (v !== undefined) openVM(v); // automatically join the vm that's in the url if it exists in the node list
res(); let v = vms.find((v) => v.id === window.location.hash.substring(1));
}); try {
if (v !== undefined) await openVM(v);
} catch (e) {
alert((e as Error).message);
}
} }
function sortVMList() { function sortVMList() {
cards.sort(function (a, b) { cards.sort((a, b) => {
return a.children[0].getAttribute('data-cvm-node')! > b.children[0].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 = ''; elements.vmlist.children[0].innerHTML = '';
@ -448,17 +458,17 @@ function sortUserList() {
} }
function chatMessage(username: string, message: string) { function chatMessage(username: string, message: string) {
var tr = document.createElement('tr'); let tr = document.createElement('tr');
var td = document.createElement('td'); let td = document.createElement('td');
// System message // System message
if (username === '') td.innerHTML = message; if (username === '') td.innerHTML = message;
else { else {
var user = VM!.getUsers().find((u) => u.username === username); let user = VM!.getUsers().find((u) => u.username === username);
var rank; let rank;
if (user !== undefined) rank = user.rank; if (user !== undefined) rank = user.rank;
else rank = Rank.Unregistered; else rank = Rank.Unregistered;
var userclass; let userclass;
var msgclass; let msgclass;
switch (rank) { switch (rank) {
case Rank.Unregistered: case Rank.Unregistered:
userclass = 'chat-username-unregistered'; userclass = 'chat-username-unregistered';
@ -489,11 +499,11 @@ function chatMessage(username: string, message: string) {
} }
function addUser(user: User) { function addUser(user: User) {
var olduser = users.find((u) => u.user === user); let olduser = users.find((u) => u.user === user);
if (olduser !== undefined) elements.userlist.removeChild(olduser.element); if (olduser !== undefined) elements.userlist.removeChild(olduser.element);
var tr = document.createElement('tr'); let tr = document.createElement('tr');
tr.setAttribute('data-cvm-turn', '-1'); tr.setAttribute('data-cvm-turn', '-1');
var td = document.createElement('td'); let td = document.createElement('td');
td.innerHTML = user.username; td.innerHTML = user.username;
switch (user.rank) { switch (user.rank) {
case Rank.Admin: case Rank.Admin:
@ -508,7 +518,7 @@ function addUser(user: User) {
} }
if (user.username === w.username) tr.classList.add('user-current'); if (user.username === w.username) tr.classList.add('user-current');
tr.appendChild(td); tr.appendChild(td);
var u = { user: user, element: tr }; let u = { user: user, element: tr };
if (rank !== Rank.Unregistered) userModOptions(u); if (rank !== Rank.Unregistered) userModOptions(u);
elements.userlist.appendChild(tr); elements.userlist.appendChild(tr);
if (olduser !== undefined) olduser.element = tr; if (olduser !== undefined) olduser.element = tr;
@ -517,14 +527,14 @@ function addUser(user: User) {
} }
function remUser(user: User) { function remUser(user: User) {
var olduser = users.findIndex((u) => u.user === user); let olduser = users.findIndex((u) => u.user === user);
if (olduser !== undefined) elements.userlist.removeChild(users[olduser].element); if (olduser !== undefined) elements.userlist.removeChild(users[olduser].element);
elements.onlineusercount.innerHTML = VM!.getUsers().length.toString(); elements.onlineusercount.innerHTML = VM!.getUsers().length.toString();
users.splice(olduser, 1); users.splice(olduser, 1);
} }
function userRenamed(oldname: string, newname: string, selfrename: boolean) { function userRenamed(oldname: string, newname: string, selfrename: boolean) {
var user = users.find((u) => u.user.username === newname); let user = users.find((u) => u.user.username === newname);
if (user) { if (user) {
user.element.children[0].innerHTML = newname; user.element.children[0].innerHTML = newname;
} }
@ -549,12 +559,12 @@ function turnUpdate(status: TurnStatus) {
enableOSK(false); enableOSK(false);
if (status.user !== null) { if (status.user !== null) {
var el = users.find((u) => u.user === status.user)!.element; let el = users.find((u) => u.user === status.user)!.element;
el!.classList.add('user-turn'); el!.classList.add('user-turn');
el!.setAttribute('data-cvm-turn', '0'); el!.setAttribute('data-cvm-turn', '0');
} }
for (const user of status.queue) { for (const user of status.queue) {
var el = users.find((u) => u.user === user)!.element; let el = users.find((u) => u.user === user)!.element;
el!.classList.add('user-waiting'); el!.classList.add('user-waiting');
el.setAttribute('data-cvm-turn', status.queue.indexOf(user).toString(10)); el.setAttribute('data-cvm-turn', status.queue.indexOf(user).toString(10));
} }
@ -626,7 +636,7 @@ elements.chatinput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendChat(); if (e.key === 'Enter') sendChat();
}); });
elements.changeUsernameBtn.addEventListener('click', () => { elements.changeUsernameBtn.addEventListener('click', () => {
var newname = prompt('Enter new username, or leave blank to be assigned a guest username', w.username); let newname = prompt('Enter new username, or leave blank to be assigned a guest username', w.username);
if (newname === w.username) return; if (newname === w.username) return;
VM?.rename(newname); VM?.rename(newname);
}); });
@ -658,7 +668,7 @@ elements.voteResetButton.addEventListener('click', () => VM?.vote(true));
elements.voteYesBtn.addEventListener('click', () => VM?.vote(true)); elements.voteYesBtn.addEventListener('click', () => VM?.vote(true));
elements.voteNoBtn.addEventListener('click', () => VM?.vote(false)); elements.voteNoBtn.addEventListener('click', () => VM?.vote(false));
// Login // Login
var usernameClick = false; let usernameClick = false;
const loginModal = new bootstrap.Modal(elements.loginModal); const loginModal = new bootstrap.Modal(elements.loginModal);
elements.loginModal.addEventListener('shown.bs.modal', () => elements.adminPassword.focus()); elements.loginModal.addEventListener('shown.bs.modal', () => elements.adminPassword.focus());
elements.username.addEventListener('click', () => { elements.username.addEventListener('click', () => {
@ -673,16 +683,16 @@ elements.loginButton.addEventListener('click', () => doLogin());
elements.adminPassword.addEventListener('keypress', (e) => e.key === 'Enter' && doLogin()); elements.adminPassword.addEventListener('keypress', (e) => e.key === 'Enter' && doLogin());
elements.incorrectPasswordDismissBtn.addEventListener('click', () => (elements.badPasswordAlert.style.display = 'none')); elements.incorrectPasswordDismissBtn.addEventListener('click', () => (elements.badPasswordAlert.style.display = 'none'));
function doLogin() { function doLogin() {
var adminPass = elements.adminPassword.value; let adminPass = elements.adminPassword.value;
if (adminPass === '') return; if (adminPass === '') return;
VM?.login(adminPass); VM?.login(adminPass);
elements.adminPassword.value = ''; elements.adminPassword.value = '';
var u = VM?.on('login', () => { let u = VM?.on('login', () => {
u!(); u!();
loginModal.hide(); loginModal.hide();
elements.badPasswordAlert.style.display = 'none'; elements.badPasswordAlert.style.display = 'none';
}); });
var _u = VM?.on('badpw', () => { let _u = VM?.on('badpw', () => {
_u!(); _u!();
elements.badPasswordAlert.style.display = 'block'; elements.badPasswordAlert.style.display = 'block';
}); });
@ -712,21 +722,21 @@ function onLogin(_rank: Rank, _perms: Permissions) {
} }
function userModOptions(user: { user: User; element: HTMLTableRowElement }) { function userModOptions(user: { user: User; element: HTMLTableRowElement }) {
var tr = user.element; let tr = user.element;
var td = tr.children[0] as HTMLTableCellElement; let td = tr.children[0] as HTMLTableCellElement;
tr.classList.add('dropdown'); tr.classList.add('dropdown');
td.classList.add('dropdown-toggle'); td.classList.add('dropdown-toggle');
td.setAttribute('data-bs-toggle', 'dropdown'); td.setAttribute('data-bs-toggle', 'dropdown');
td.setAttribute('role', 'button'); td.setAttribute('role', 'button');
td.setAttribute('aria-expanded', 'false'); td.setAttribute('aria-expanded', 'false');
var ul = document.createElement('ul'); let ul = document.createElement('ul');
ul.classList.add('dropdown-menu', 'dropdown-menu-dark', 'table-dark', 'text-light'); ul.classList.add('dropdown-menu', 'dropdown-menu-dark', 'table-dark', 'text-light');
if (perms.bypassturn) addUserDropdownItem(ul, 'End Turn', () => VM!.endTurn(user.user.username)); if (perms.bypassturn) addUserDropdownItem(ul, 'End Turn', () => VM!.endTurn(user.user.username));
if (perms.ban) addUserDropdownItem(ul, 'Ban', () => VM!.ban(user.user.username)); if (perms.ban) addUserDropdownItem(ul, 'Ban', () => VM!.ban(user.user.username));
if (perms.kick) addUserDropdownItem(ul, 'Kick', () => VM!.kick(user.user.username)); if (perms.kick) addUserDropdownItem(ul, 'Kick', () => VM!.kick(user.user.username));
if (perms.rename) if (perms.rename)
addUserDropdownItem(ul, 'Rename', () => { addUserDropdownItem(ul, 'Rename', () => {
var newname = prompt(`Enter new username for ${user.user.username}`); let newname = prompt(`Enter new username for ${user.user.username}`);
if (!newname) return; if (!newname) return;
VM!.renameUser(user.user.username, newname); VM!.renameUser(user.user.username, newname);
}); });
@ -737,15 +747,15 @@ function userModOptions(user: { user: User; element: HTMLTableRowElement }) {
} }
if (perms.grabip) if (perms.grabip)
addUserDropdownItem(ul, 'Get IP', async () => { addUserDropdownItem(ul, 'Get IP', async () => {
var ip = await VM!.getip(user.user.username); let ip = await VM!.getip(user.user.username);
alert(ip); alert(ip);
}); });
tr.appendChild(ul); tr.appendChild(ul);
} }
function addUserDropdownItem(ul: HTMLUListElement, text: string, func: () => void) { function addUserDropdownItem(ul: HTMLUListElement, text: string, func: () => void) {
var li = document.createElement('li'); let li = document.createElement('li');
var a = document.createElement('a'); let a = document.createElement('a');
a.href = '#'; a.href = '#';
a.classList.add('dropdown-item'); a.classList.add('dropdown-item');
a.innerHTML = text; a.innerHTML = text;
@ -760,7 +770,7 @@ elements.rebootBtn.addEventListener('click', () => VM?.reboot());
elements.clearQueueBtn.addEventListener('click', () => VM?.clearQueue()); elements.clearQueueBtn.addEventListener('click', () => VM?.clearQueue());
elements.bypassTurnBtn.addEventListener('click', () => VM?.bypassTurn()); elements.bypassTurnBtn.addEventListener('click', () => VM?.bypassTurn());
elements.endTurnBtn.addEventListener('click', () => { elements.endTurnBtn.addEventListener('click', () => {
var user = VM?.getUsers().find((u) => u.turn === 0); let user = VM?.getUsers().find((u) => u.turn === 0);
if (user) VM?.endTurn(user.username); if (user) VM?.endTurn(user.username);
}); });
elements.forceVoteNoBtn.addEventListener('click', () => VM?.forceVote(false)); elements.forceVoteNoBtn.addEventListener('click', () => VM?.forceVote(false));
@ -769,10 +779,10 @@ elements.indefTurnBtn.addEventListener('click', () => VM?.indefiniteTurn());
async function sendQEMUCommand() { async function sendQEMUCommand() {
if (!elements.qemuMonitorInput.value) return; if (!elements.qemuMonitorInput.value) return;
var cmd = elements.qemuMonitorInput.value; let cmd = elements.qemuMonitorInput.value;
elements.qemuMonitorOutput.innerHTML += `&gt; ${cmd}\n`; elements.qemuMonitorOutput.innerHTML += `&gt; ${cmd}\n`;
elements.qemuMonitorInput.value = ''; elements.qemuMonitorInput.value = '';
var response = await VM?.qemuMonitor(cmd); let response = await VM?.qemuMonitor(cmd);
elements.qemuMonitorOutput.innerHTML += `${response}\n`; elements.qemuMonitorOutput.innerHTML += `${response}\n`;
elements.qemuMonitorOutput.scrollTop = elements.qemuMonitorOutput.scrollHeight; elements.qemuMonitorOutput.scrollTop = elements.qemuMonitorOutput.scrollHeight;
} }
@ -830,10 +840,10 @@ w.VMName = null;
loadList(); loadList();
// Welcome modal // Welcome modal
var noWelcomeModal = window.localStorage.getItem('no-welcome-modal'); let noWelcomeModal = window.localStorage.getItem('no-welcome-modal');
if (noWelcomeModal !== '1') { if (noWelcomeModal !== '1') {
var welcomeModalDismissBtn = document.getElementById('welcomeModalDismiss') as HTMLButtonElement; let welcomeModalDismissBtn = document.getElementById('welcomeModalDismiss') as HTMLButtonElement;
var welcomeModal = new bootstrap.Modal(document.getElementById('welcomeModal') as HTMLDivElement); let welcomeModal = new bootstrap.Modal(document.getElementById('welcomeModal') as HTMLDivElement);
welcomeModalDismissBtn.addEventListener('click', () => { welcomeModalDismissBtn.addEventListener('click', () => {
window.localStorage.setItem('no-welcome-modal', '1'); window.localStorage.setItem('no-welcome-modal', '1');
}); });