add support for country flags
This commit is contained in:
parent
67413079b0
commit
03be418d97
|
|
@ -33,5 +33,6 @@
|
|||
"run-script-os": "^1.1.6",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,40 +87,40 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
tr.user-admin > td, .chat-username-admin, .username-admin {
|
||||
tr.user-admin .userlist-username, .chat-username-admin, .username-admin {
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
tr.user-moderator > td, .chat-username-moderator, .username-moderator {
|
||||
tr.user-moderator .userlist-username, .chat-username-moderator, .username-moderator {
|
||||
color: #00FF00 !important;
|
||||
}
|
||||
|
||||
html[data-bs-theme="dark"] {
|
||||
tr.user-unregistered > td, .chat-username-unregistered, .username-unregistered {
|
||||
tr.user-unregistered .userlist-username, .chat-username-unregistered, .username-unregistered {
|
||||
color: #b1b1b1 !important;
|
||||
}
|
||||
|
||||
tr.user-registered > td, .chat-username-registered, .username-registered {
|
||||
tr.user-registered .userlist-username, .chat-username-registered, .username-registered {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
tr.user-registered.user-turn > td, tr.user-registered.user-waiting > td {
|
||||
tr.user-registered.user-turn .userlist-username, tr.user-registered.user-waiting .userlist-username {
|
||||
color: #000000 !important;
|
||||
--bs-table-color: #000000 !important;
|
||||
}
|
||||
|
||||
tr.user-unregistered.user-turn > td, tr.user-unregistered.user-waiting > td {
|
||||
tr.user-unregistered.user-turn .userlist-username, tr.user-unregistered.user-waiting .userlist-username {
|
||||
color: #585858 !important;
|
||||
--bs-table-color: #585858 !important;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-bs-theme="light"] {
|
||||
tr.user-unregistered > td, .chat-username-unregistered, .username-unregistered {
|
||||
tr.user-unregistered .userlist-username, .chat-username-unregistered, .username-unregistered {
|
||||
color: #6b6b6b !important;
|
||||
}
|
||||
|
||||
tr.user-registered > td, .chat-username-registered, .username-registered {
|
||||
tr.user-registered .userlist-username, .chat-username-registered, .username-registered {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ tr.user-waiting > td {
|
|||
--bs-table-bg-state: #ece1be !important;
|
||||
}
|
||||
|
||||
.user-current {
|
||||
.user-current .userlist-username {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
|
@ -340,3 +340,11 @@ Theme: cvmDisabled
|
|||
font-family: 'Noto Color Emoji';
|
||||
src: url('../assets/NotoColorEmoji.ttf');
|
||||
}
|
||||
|
||||
.userlist-flag {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.userlist-flag:empty {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -141,6 +141,7 @@
|
|||
<input id="accountSettingsConfirmNewPassword" type="password" class="form-control" name="confirmpassword"/><br/>
|
||||
<label for="accountSettingsCurrentPassword" id="accountSettingsCurrentPasswordLabel"></label>
|
||||
<input id="accountSettingsCurrentPassword" type="password" class="form-control" name="currentpassword" required/><br/>
|
||||
<input type="checkbox" id="hideFlagCheckbox" class="form-check-input"/> <label for="hideFlagCheckbox" id="hideFlagCheckboxLabel"></label><br/>
|
||||
<button type="submit" class="btn btn-primary" id="updateAccountSettingsBtn"></button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ const fallbackLanguage : Language = {
|
|||
"kAccountModal_ConfirmNewPassword": "Confirm New Password",
|
||||
"kAccountModal_CurrentPassword": "Current Password",
|
||||
"kAccountModal_ConfirmPassword": "Confirm Password",
|
||||
"kAccountModal_HideFlag": "Hide my Country Flag",
|
||||
|
||||
"kMissingCaptcha": "Please fill out the captcha.",
|
||||
"kPasswordsMustMatch": "Passwords must match.",
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ export enum I18nStringKey {
|
|||
kAccountModal_ConfirmNewPassword = 'kAccountModal_ConfirmNewPassword',
|
||||
kAccountModal_CurrentPassword = 'kAccountModal_CurrentPassword',
|
||||
kAccountModal_ConfirmPassword = 'kAccountModal_ConfirmPassword',
|
||||
kAccountModal_HideFlag = 'kAccountModal_HideFlag',
|
||||
|
||||
kAccountModal_VerifyText = 'kAccountModal_VerifyText',
|
||||
kAccountModal_VerifyPasswordResetText = 'kAccountModal_VerifyPasswordResetText',
|
||||
|
|
@ -295,6 +296,7 @@ export class I18n {
|
|||
accountSettingsNewPasswordLabel: I18nStringKey.kAccountModal_NewPassword,
|
||||
accountSettingsConfirmNewPasswordLabel: I18nStringKey.kAccountModal_ConfirmNewPassword,
|
||||
accountSettingsCurrentPasswordLabel: I18nStringKey.kAccountModal_CurrentPassword,
|
||||
hideFlagCheckboxLabel: I18nStringKey.kAccountModal_HideFlag,
|
||||
updateAccountSettingsBtn: I18nStringKey.kGeneric_Update,
|
||||
accountResetPasswordEmailLabel: I18nStringKey.kGeneric_EMail,
|
||||
accountResetPasswordUsernameLabel: I18nStringKey.kGeneric_Username,
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ const elements = {
|
|||
accountSettingsNewPassword: document.getElementById("accountSettingsNewPassword") as HTMLInputElement,
|
||||
accountSettingsConfirmNewPassword: document.getElementById("accountSettingsConfirmNewPassword") as HTMLInputElement,
|
||||
accountSettingsCurrentPassword: document.getElementById("accountSettingsCurrentPassword") as HTMLInputElement,
|
||||
hideFlagCheckbox: document.getElementById("hideFlagCheckbox") as HTMLInputElement,
|
||||
|
||||
accountResetPasswordSection: document.getElementById("accountResetPasswordSection") as HTMLDivElement,
|
||||
accountResetPasswordForm: document.getElementById("accountResetPasswordForm") as HTMLFormElement,
|
||||
|
|
@ -316,6 +317,8 @@ const vms: VM[] = [];
|
|||
const cards: HTMLDivElement[] = [];
|
||||
const users: {
|
||||
user: User;
|
||||
usernameElement: HTMLSpanElement;
|
||||
flagElement: HTMLSpanElement;
|
||||
element: HTMLTableRowElement;
|
||||
}[] = [];
|
||||
let turnInterval: number | undefined = undefined;
|
||||
|
|
@ -392,6 +395,7 @@ async function openVM(vm: VM): Promise<void> {
|
|||
|
||||
VM!.on('chat', (username, message) => chatMessage(username, message));
|
||||
VM!.on('adduser', (user) => addUser(user));
|
||||
VM!.on('flag', () => flag());
|
||||
VM!.on('remuser', (user) => remUser(user));
|
||||
VM!.on('rename', (oldname, newname, selfrename) => userRenamed(oldname, newname, selfrename));
|
||||
|
||||
|
|
@ -598,7 +602,14 @@ function addUser(user: User) {
|
|||
let tr = document.createElement('tr');
|
||||
tr.setAttribute('data-cvm-turn', '-1');
|
||||
let td = document.createElement('td');
|
||||
td.innerHTML = user.username;
|
||||
let flagSpan = document.createElement('span');
|
||||
let usernameSpan = document.createElement('span');
|
||||
flagSpan.classList.add("userlist-flag");
|
||||
usernameSpan.classList.add("userlist-username");
|
||||
td.appendChild(flagSpan);
|
||||
if (user.countryCode !== null) flagSpan.innerHTML = getFlagEmoji(user.countryCode);
|
||||
td.appendChild(usernameSpan);
|
||||
usernameSpan.innerText = user.username;
|
||||
switch (user.rank) {
|
||||
case Rank.Admin:
|
||||
tr.classList.add('user-admin');
|
||||
|
|
@ -615,7 +626,7 @@ function addUser(user: User) {
|
|||
}
|
||||
if (user.username === w.username) tr.classList.add('user-current');
|
||||
tr.appendChild(td);
|
||||
let u = { user: user, element: tr };
|
||||
let u = { user: user, element: tr, usernameElement: usernameSpan, flagElement: flagSpan };
|
||||
if (rank === Rank.Admin || rank === Rank.Moderator) userModOptions(u);
|
||||
elements.userlist.appendChild(tr);
|
||||
if (olduser !== undefined) olduser.element = tr;
|
||||
|
|
@ -630,10 +641,21 @@ function remUser(user: User) {
|
|||
users.splice(olduser, 1);
|
||||
}
|
||||
|
||||
function getFlagEmoji(countryCode: string) {
|
||||
if (countryCode.length !== 2) throw new Error('Invalid country code');
|
||||
return String.fromCodePoint(...countryCode.toUpperCase().split('').map(char => 127397 + char.charCodeAt(0)));
|
||||
}
|
||||
|
||||
function flag() {
|
||||
for (let user of users.filter(u => u.user.countryCode !== null)) {
|
||||
user.flagElement.innerHTML = getFlagEmoji(user.user.countryCode!);
|
||||
}
|
||||
}
|
||||
|
||||
function userRenamed(oldname: string, newname: string, selfrename: boolean) {
|
||||
let user = users.find((u) => u.user.username === newname);
|
||||
if (user) {
|
||||
user.element.children[0].innerHTML = newname;
|
||||
user.usernameElement.innerHTML = newname;
|
||||
}
|
||||
if (selfrename) {
|
||||
w.username = newname;
|
||||
|
|
@ -1110,6 +1132,11 @@ elements.accountSettingsForm.addEventListener('submit', async e => {
|
|||
elements.accountModalError.style.display = "block";
|
||||
return false;
|
||||
}
|
||||
localStorage.setItem("collabvm-hide-flag", JSON.stringify(elements.hideFlagCheckbox.checked));
|
||||
if (!password && !email && !username) {
|
||||
accountModal.hide();
|
||||
return false
|
||||
}
|
||||
var result = await auth!.updateAccount(currentPassword, email, username, password);
|
||||
if (result.success) {
|
||||
elements.accountSettingsNewPassword.value = "";
|
||||
|
|
@ -1311,6 +1338,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
renderAuth();
|
||||
}
|
||||
|
||||
var hideFlag = JSON.parse(localStorage.getItem("collabvm-hide-flag")!);
|
||||
if (hideFlag === null) hideFlag = false;
|
||||
elements.hideFlagCheckbox.checked = hideFlag;
|
||||
|
||||
document.title = TheI18n.GetString(I18nStringKey.kGeneric_CollabVM);
|
||||
|
||||
// Load all VMs
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ export interface CollabVMClientEvents {
|
|||
// Auth stuff
|
||||
auth: (server: string) => void;
|
||||
accountlogin: (success: boolean) => void;
|
||||
|
||||
flag: () => void;
|
||||
}
|
||||
|
||||
// types for private emitter
|
||||
|
|
@ -413,6 +415,14 @@ export default class CollabVMClient {
|
|||
}
|
||||
}
|
||||
}
|
||||
case 'flag': {
|
||||
for (let i = 1; i < msgArr.length; i += 2) {
|
||||
let user = this.users.find((u) => u.username === msgArr[i]);
|
||||
if (user) user.countryCode = msgArr[i + 1];
|
||||
}
|
||||
this.publicEmitter.emit('flag');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -493,6 +503,7 @@ export default class CollabVMClient {
|
|||
u();
|
||||
res(success);
|
||||
});
|
||||
if (localStorage.getItem('collabvm-hide-flag') === 'true') this.send('noflag');
|
||||
if (username === null) this.send('rename');
|
||||
else this.send('rename', username);
|
||||
this.send('connect', id);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ export class User {
|
|||
rank: Rank;
|
||||
// -1 means not in the turn queue, 0 means the current turn, anything else is the position in the queue
|
||||
turn: number;
|
||||
countryCode: string | null = null;
|
||||
|
||||
constructor(username: string, rank: Rank = Rank.Unregistered) {
|
||||
this.username = username;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
"kAccountModal_ConfirmNewPassword": "Confirm New Password",
|
||||
"kAccountModal_CurrentPassword": "Current Password",
|
||||
"kAccountModal_ConfirmPassword": "Confirm Password",
|
||||
"kAccountModal_HideFlag": "Hide my Country Flag",
|
||||
|
||||
"kMissingCaptcha": "Please fill out the captcha.",
|
||||
"kPasswordsMustMatch": "Passwords must match.",
|
||||
|
|
|
|||
22
yarn.lock
22
yarn.lock
|
|
@ -1441,6 +1441,13 @@
|
|||
dependencies:
|
||||
"@popperjs/core" "^2.9.2"
|
||||
|
||||
"@types/dompurify@^3.0.5":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
|
||||
integrity sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==
|
||||
dependencies:
|
||||
"@types/trusted-types" "*"
|
||||
|
||||
"@types/graceful-fs@^4.1.3":
|
||||
version "4.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4"
|
||||
|
|
@ -1487,6 +1494,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
|
||||
integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
|
||||
|
||||
"@types/trusted-types@*":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
|
||||
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
|
||||
|
|
@ -1864,6 +1876,11 @@ csso@^4.2.0:
|
|||
dependencies:
|
||||
css-tree "^1.1.2"
|
||||
|
||||
dayjs@^1.11.10:
|
||||
version "1.11.11"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
|
||||
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
|
|
@ -1922,6 +1939,11 @@ domhandler@^4.2.0, domhandler@^4.2.2, domhandler@^4.3.1:
|
|||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
dompurify@^3.1.0:
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.5.tgz#2c6a113fc728682a0f55684b1388c58ddb79dc38"
|
||||
integrity sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==
|
||||
|
||||
domutils@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user