mirror of
https://git.sanhost.net/sanasol/hytale-f2p.git
synced 2026-02-27 07:11:47 -03:00
v2.4.4: Rename Profiles to Configurations, add Identity Switcher
- Rename "Profiles" to "Configurations" in all UI text and 11 locale files - Add identity switcher dropdown in header (green accent, fa-id-badge icon) - Quick-switch player identity without opening Settings - "Manage" action opens UUID Management modal - Header tooltips explaining what each dropdown does - Config dropdown icon changed from fa-user-circle to fa-sliders-h - Global Escape key handler for closing modals and dropdowns - Fix identity selector not clickable (missing -webkit-app-region: no-drag) - Sync header identity name after all identity-changing operations - XSS protection in identity list rendering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,10 +18,15 @@ let regenerateUuidBtn;
|
||||
let manageUuidsBtn;
|
||||
let uuidModal;
|
||||
let uuidModalClose;
|
||||
let modalCurrentUuid;
|
||||
let modalCopyUuidBtn;
|
||||
let modalRegenerateUuidBtn;
|
||||
let generateNewUuidBtn;
|
||||
let addIdentityBtn;
|
||||
let uuidAddForm;
|
||||
let addIdentityUsername;
|
||||
let addIdentityUuid;
|
||||
let addIdentityRegenerateBtn;
|
||||
let addIdentityConfirmBtn;
|
||||
let addIdentityCancelBtn;
|
||||
let uuidAdvancedToggle;
|
||||
let uuidAdvancedContent;
|
||||
let uuidList;
|
||||
let customUuidInput;
|
||||
let setCustomUuidBtn;
|
||||
@@ -180,10 +185,15 @@ function setupSettingsElements() {
|
||||
manageUuidsBtn = document.getElementById('manageUuidsBtn');
|
||||
uuidModal = document.getElementById('uuidModal');
|
||||
uuidModalClose = document.getElementById('uuidModalClose');
|
||||
modalCurrentUuid = document.getElementById('modalCurrentUuid');
|
||||
modalCopyUuidBtn = document.getElementById('modalCopyUuidBtn');
|
||||
modalRegenerateUuidBtn = document.getElementById('modalRegenerateUuidBtn');
|
||||
generateNewUuidBtn = document.getElementById('generateNewUuidBtn');
|
||||
addIdentityBtn = document.getElementById('addIdentityBtn');
|
||||
uuidAddForm = document.getElementById('uuidAddForm');
|
||||
addIdentityUsername = document.getElementById('addIdentityUsername');
|
||||
addIdentityUuid = document.getElementById('addIdentityUuid');
|
||||
addIdentityRegenerateBtn = document.getElementById('addIdentityRegenerateBtn');
|
||||
addIdentityConfirmBtn = document.getElementById('addIdentityConfirmBtn');
|
||||
addIdentityCancelBtn = document.getElementById('addIdentityCancelBtn');
|
||||
uuidAdvancedToggle = document.getElementById('uuidAdvancedToggle');
|
||||
uuidAdvancedContent = document.getElementById('uuidAdvancedContent');
|
||||
uuidList = document.getElementById('uuidList');
|
||||
customUuidInput = document.getElementById('customUuidInput');
|
||||
setCustomUuidBtn = document.getElementById('setCustomUuidBtn');
|
||||
@@ -230,16 +240,24 @@ function setupSettingsElements() {
|
||||
uuidModalClose.addEventListener('click', closeUuidModal);
|
||||
}
|
||||
|
||||
if (modalCopyUuidBtn) {
|
||||
modalCopyUuidBtn.addEventListener('click', copyCurrentUuid);
|
||||
if (addIdentityBtn) {
|
||||
addIdentityBtn.addEventListener('click', showAddIdentityForm);
|
||||
}
|
||||
|
||||
if (modalRegenerateUuidBtn) {
|
||||
modalRegenerateUuidBtn.addEventListener('click', regenerateCurrentUuid);
|
||||
if (addIdentityRegenerateBtn) {
|
||||
addIdentityRegenerateBtn.addEventListener('click', regenerateAddIdentityUuid);
|
||||
}
|
||||
|
||||
if (generateNewUuidBtn) {
|
||||
generateNewUuidBtn.addEventListener('click', generateNewUuid);
|
||||
if (addIdentityConfirmBtn) {
|
||||
addIdentityConfirmBtn.addEventListener('click', confirmAddIdentity);
|
||||
}
|
||||
|
||||
if (addIdentityCancelBtn) {
|
||||
addIdentityCancelBtn.addEventListener('click', hideAddIdentityForm);
|
||||
}
|
||||
|
||||
if (uuidAdvancedToggle) {
|
||||
uuidAdvancedToggle.addEventListener('click', toggleAdvancedSection);
|
||||
}
|
||||
|
||||
if (setCustomUuidBtn) {
|
||||
@@ -467,6 +485,9 @@ async function savePlayerName() {
|
||||
// Also refresh the UUID list to update which entry is marked as current
|
||||
await loadAllUuids();
|
||||
|
||||
// Refresh header identity dropdown
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error saving player name:', error);
|
||||
const errorMsg = window.i18n ? window.i18n.t('notifications.playerNameSaveFailed') : 'Failed to save player name';
|
||||
@@ -630,7 +651,6 @@ async function loadCurrentUuid() {
|
||||
const uuid = await window.electronAPI.getCurrentUuid();
|
||||
if (uuid) {
|
||||
if (currentUuidDisplay) currentUuidDisplay.value = uuid;
|
||||
if (modalCurrentUuid) modalCurrentUuid.value = uuid;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -640,7 +660,7 @@ async function loadCurrentUuid() {
|
||||
|
||||
async function copyCurrentUuid() {
|
||||
try {
|
||||
const uuid = currentUuidDisplay ? currentUuidDisplay.value : modalCurrentUuid?.value;
|
||||
const uuid = currentUuidDisplay ? currentUuidDisplay.value : null;
|
||||
if (uuid && navigator.clipboard) {
|
||||
await navigator.clipboard.writeText(uuid);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidCopied') : 'UUID copied to clipboard!';
|
||||
@@ -688,13 +708,13 @@ async function performRegenerateUuid() {
|
||||
const result = await window.electronAPI.resetCurrentUserUuid();
|
||||
if (result.success && result.uuid) {
|
||||
if (currentUuidDisplay) currentUuidDisplay.value = result.uuid;
|
||||
if (modalCurrentUuid) modalCurrentUuid.value = result.uuid;
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidGenerated') : 'New UUID generated successfully!';
|
||||
showNotification(msg, 'success');
|
||||
|
||||
if (uuidModal && uuidModal.style.display !== 'none') {
|
||||
await loadAllUuids();
|
||||
}
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to generate new UUID');
|
||||
}
|
||||
@@ -717,6 +737,10 @@ async function openUuidModal() {
|
||||
}
|
||||
}
|
||||
|
||||
// Expose globally so identity dropdown and Escape handler can use them
|
||||
window.openUuidModal = openUuidModal;
|
||||
window.loadCurrentUuid = loadCurrentUuid;
|
||||
|
||||
function closeUuidModal() {
|
||||
if (uuidModal) {
|
||||
uuidModal.classList.remove('active');
|
||||
@@ -725,6 +749,7 @@ function closeUuidModal() {
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
window.closeUuidModal = closeUuidModal;
|
||||
|
||||
async function loadAllUuids() {
|
||||
try {
|
||||
@@ -769,6 +794,9 @@ async function loadAllUuids() {
|
||||
<button class="uuid-item-btn copy" onclick="copyUuid('${mapping.uuid}')" title="Copy UUID">
|
||||
<i class="fas fa-copy"></i>
|
||||
</button>
|
||||
${mapping.isCurrent ? `<button class="uuid-item-btn regenerate" onclick="regenerateUuidForUser('${escapeHtml(mapping.username)}')" title="Regenerate UUID">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
</button>` : ''}
|
||||
${!mapping.isCurrent ? `<button class="uuid-item-btn delete" onclick="deleteUuid('${escapeHtml(mapping.username)}')" title="Delete UUID">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>` : ''}
|
||||
@@ -791,23 +819,119 @@ async function loadAllUuids() {
|
||||
}
|
||||
}
|
||||
|
||||
async function generateNewUuid() {
|
||||
async function showAddIdentityForm() {
|
||||
if (!uuidAddForm) return;
|
||||
uuidAddForm.style.display = 'block';
|
||||
if (addIdentityUsername) {
|
||||
addIdentityUsername.value = '';
|
||||
addIdentityUsername.focus();
|
||||
}
|
||||
if (addIdentityUuid) {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.generateNewUuid) {
|
||||
const newUuid = await window.electronAPI.generateNewUuid();
|
||||
if (newUuid) addIdentityUuid.value = newUuid;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error pre-generating UUID:', e);
|
||||
}
|
||||
}
|
||||
if (addIdentityBtn) addIdentityBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
function hideAddIdentityForm() {
|
||||
if (uuidAddForm) uuidAddForm.style.display = 'none';
|
||||
if (addIdentityBtn) addIdentityBtn.style.display = '';
|
||||
}
|
||||
|
||||
async function regenerateAddIdentityUuid() {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.generateNewUuid) {
|
||||
const newUuid = await window.electronAPI.generateNewUuid();
|
||||
if (newUuid) {
|
||||
if (customUuidInput) customUuidInput.value = newUuid;
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidGeneratedShort') : 'New UUID generated!';
|
||||
showNotification(msg, 'success');
|
||||
if (newUuid && addIdentityUuid) {
|
||||
addIdentityUuid.value = newUuid;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generating new UUID:', error);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidGenerateFailed') : 'Failed to generate new UUID';
|
||||
console.error('Error generating UUID:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmAddIdentity() {
|
||||
try {
|
||||
const username = addIdentityUsername ? addIdentityUsername.value.trim() : '';
|
||||
const uuid = addIdentityUuid ? addIdentityUuid.value.trim() : '';
|
||||
|
||||
if (!username) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.playerNameRequired') : 'Please enter a username';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (username.length > 16) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.playerNameTooLong') : 'Username must be 16 characters or less';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
if (!uuid || !uuidRegex.test(uuid)) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidInvalidFormat') : 'Invalid UUID format';
|
||||
showNotification(msg, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.electronAPI && window.electronAPI.setUuidForUser) {
|
||||
const result = await window.electronAPI.setUuidForUser(username, uuid);
|
||||
if (result.success) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.identityAdded') : 'Identity added successfully!';
|
||||
showNotification(msg, 'success');
|
||||
hideAddIdentityForm();
|
||||
await loadAllUuids();
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to add identity');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error adding identity:', error);
|
||||
const msg = window.i18n ? window.i18n.t('notifications.identityAddFailed') : 'Failed to add identity';
|
||||
showNotification(msg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAdvancedSection() {
|
||||
if (!uuidAdvancedContent || !uuidAdvancedToggle) return;
|
||||
const isOpen = uuidAdvancedContent.style.display !== 'none';
|
||||
uuidAdvancedContent.style.display = isOpen ? 'none' : 'block';
|
||||
const chevron = uuidAdvancedToggle.querySelector('.uuid-advanced-chevron');
|
||||
if (chevron) {
|
||||
chevron.classList.toggle('open', !isOpen);
|
||||
}
|
||||
}
|
||||
|
||||
window.regenerateUuidForUser = async function (username) {
|
||||
try {
|
||||
const message = window.i18n ? window.i18n.t('confirm.regenerateUuidMessage') : 'Are you sure you want to generate a new UUID? This will change your player identity.';
|
||||
const title = window.i18n ? window.i18n.t('confirm.regenerateUuidTitle') : 'Generate New UUID';
|
||||
const confirmBtn = window.i18n ? window.i18n.t('confirm.regenerateUuidButton') : 'Generate';
|
||||
const cancelBtn = window.i18n ? window.i18n.t('common.cancel') : 'Cancel';
|
||||
|
||||
showCustomConfirm(
|
||||
message,
|
||||
title,
|
||||
async () => {
|
||||
await performRegenerateUuid();
|
||||
},
|
||||
null,
|
||||
confirmBtn,
|
||||
cancelBtn
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error regenerating UUID:', error);
|
||||
}
|
||||
};
|
||||
|
||||
async function setCustomUuid() {
|
||||
try {
|
||||
if (!customUuidInput || !customUuidInput.value.trim()) {
|
||||
@@ -865,13 +989,13 @@ async function performSetCustomUuid(uuid) {
|
||||
|
||||
if (result.success) {
|
||||
if (currentUuidDisplay) currentUuidDisplay.value = uuid;
|
||||
if (modalCurrentUuid) modalCurrentUuid.value = uuid;
|
||||
if (customUuidInput) customUuidInput.value = '';
|
||||
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidSetSuccess') : 'Custom UUID set successfully!';
|
||||
showNotification(msg, 'success');
|
||||
|
||||
await loadAllUuids();
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to set custom UUID');
|
||||
}
|
||||
@@ -950,6 +1074,9 @@ async function performSwitchToUsername(username) {
|
||||
// Refresh the UUID list to show new "Current" badge
|
||||
await loadAllUuids();
|
||||
|
||||
// Refresh header identity dropdown
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
|
||||
const msg = window.i18n
|
||||
? window.i18n.t('notifications.switchUsernameSuccess').replace('{username}', username)
|
||||
: `Switched to "${username}" successfully!`;
|
||||
@@ -997,6 +1124,7 @@ async function performDeleteUuid(username) {
|
||||
const msg = window.i18n ? window.i18n.t('notifications.uuidDeleteSuccess') : 'UUID deleted successfully!';
|
||||
showNotification(msg, 'success');
|
||||
await loadAllUuids();
|
||||
if (window.loadIdentities) window.loadIdentities();
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to delete UUID');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user