Implement password prompt UI and logic in MultiChatDialog: Add a password entry panel with validation and error handling for room access. Update i18n files for localized password prompts in English, German, and Spanish.
This commit is contained in:
@@ -172,6 +172,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="!showColorPicker && passwordPromptVisible" class="room-password-panel">
|
||||||
|
<div class="room-password-title">{{ $t('chat.multichat.password.title') }}</div>
|
||||||
|
<div class="room-password-message">
|
||||||
|
{{ passwordPromptInvalid ? $t('chat.multichat.password.invalidPrompt', { room: passwordPromptRoom }) : $t('chat.multichat.password.requiredPrompt', { room: passwordPromptRoom }) }}
|
||||||
|
</div>
|
||||||
|
<div class="room-password-controls">
|
||||||
|
<input
|
||||||
|
v-model="passwordPromptValue"
|
||||||
|
class="room-password-input"
|
||||||
|
type="password"
|
||||||
|
:placeholder="$t('chat.multichat.password.inputLabel')"
|
||||||
|
@keyup.enter="submitRoomPassword"
|
||||||
|
/>
|
||||||
|
<button type="button" class="send-btn" @click="submitRoomPassword">{{ $t('chat.multichat.password.submit') }}</button>
|
||||||
|
<button type="button" class="create-room-reset-btn" @click="cancelRoomPassword">{{ $t('chat.multichat.password.cancel') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="!showColorPicker" class="multi-chat-input">
|
<div v-if="!showColorPicker" class="multi-chat-input">
|
||||||
<input v-model="input" @keyup.enter="sendMessage" class="chat-input"
|
<input v-model="input" @keyup.enter="sendMessage" class="chat-input"
|
||||||
:placeholder="$t('chat.multichat.placeholder')" />
|
:placeholder="$t('chat.multichat.placeholder')" />
|
||||||
@@ -322,7 +339,10 @@ export default {
|
|||||||
pendingRoomCreateAttempts: 0,
|
pendingRoomCreateAttempts: 0,
|
||||||
pendingRoomCreateTimer: null,
|
pendingRoomCreateTimer: null,
|
||||||
roomPasswords: {},
|
roomPasswords: {},
|
||||||
passwordPromptActive: false,
|
passwordPromptVisible: false,
|
||||||
|
passwordPromptInvalid: false,
|
||||||
|
passwordPromptRoom: '',
|
||||||
|
passwordPromptValue: '',
|
||||||
// Palette state
|
// Palette state
|
||||||
paletteWidth: 420,
|
paletteWidth: 420,
|
||||||
paletteHeight: 220,
|
paletteHeight: 220,
|
||||||
@@ -371,6 +391,10 @@ export default {
|
|||||||
this.messages = [];
|
this.messages = [];
|
||||||
this.usersInRoom = [];
|
this.usersInRoom = [];
|
||||||
this.selectedTargetUser = null;
|
this.selectedTargetUser = null;
|
||||||
|
this.passwordPromptVisible = false;
|
||||||
|
this.passwordPromptInvalid = false;
|
||||||
|
this.passwordPromptRoom = '';
|
||||||
|
this.passwordPromptValue = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -411,38 +435,47 @@ export default {
|
|||||||
if (!roomName) return '';
|
if (!roomName) return '';
|
||||||
return this.roomPasswords[roomName] || '';
|
return this.roomPasswords[roomName] || '';
|
||||||
},
|
},
|
||||||
async handleRoomPasswordError(errorCode) {
|
handleRoomPasswordError(errorCode) {
|
||||||
const room = this.getSelectedRoomName();
|
const room = this.getSelectedRoomName();
|
||||||
if (!room || this.passwordPromptActive) return;
|
if (!room || this.passwordPromptVisible) return;
|
||||||
this.passwordPromptActive = true;
|
this.passwordPromptRoom = room;
|
||||||
try {
|
this.passwordPromptInvalid = errorCode === 'room_password_invalid';
|
||||||
const isInvalid = errorCode === 'room_password_invalid';
|
this.passwordPromptValue = '';
|
||||||
const promptText = isInvalid
|
this.passwordPromptVisible = true;
|
||||||
? this.$t('chat.multichat.password.invalidPrompt', { room })
|
},
|
||||||
: this.$t('chat.multichat.password.requiredPrompt', { room });
|
submitRoomPassword() {
|
||||||
const entered = window.prompt(promptText, '');
|
const room = this.passwordPromptRoom || this.getSelectedRoomName();
|
||||||
if (entered === null) {
|
if (!room) {
|
||||||
this.messages.push({
|
this.passwordPromptVisible = false;
|
||||||
id: Date.now(),
|
return;
|
||||||
user: 'System',
|
|
||||||
text: this.$t('chat.multichat.password.cancelled', { room })
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const password = entered.trim();
|
|
||||||
if (!password) {
|
|
||||||
this.messages.push({
|
|
||||||
id: Date.now(),
|
|
||||||
user: 'System',
|
|
||||||
text: this.$t('chat.multichat.password.empty')
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.roomPasswords[room] = password;
|
|
||||||
this.sendWithToken({ type: 'join', room, password });
|
|
||||||
} finally {
|
|
||||||
this.passwordPromptActive = false;
|
|
||||||
}
|
}
|
||||||
|
const password = (this.passwordPromptValue || '').trim();
|
||||||
|
if (!password) {
|
||||||
|
this.messages.push({
|
||||||
|
id: Date.now(),
|
||||||
|
user: 'System',
|
||||||
|
text: this.$t('chat.multichat.password.empty')
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.roomPasswords[room] = password;
|
||||||
|
this.passwordPromptVisible = false;
|
||||||
|
this.passwordPromptInvalid = false;
|
||||||
|
this.passwordPromptRoom = '';
|
||||||
|
this.passwordPromptValue = '';
|
||||||
|
this.sendWithToken({ type: 'join', room, password });
|
||||||
|
},
|
||||||
|
cancelRoomPassword() {
|
||||||
|
const room = this.passwordPromptRoom || this.getSelectedRoomName();
|
||||||
|
this.passwordPromptVisible = false;
|
||||||
|
this.passwordPromptInvalid = false;
|
||||||
|
this.passwordPromptRoom = '';
|
||||||
|
this.passwordPromptValue = '';
|
||||||
|
this.messages.push({
|
||||||
|
id: Date.now(),
|
||||||
|
user: 'System',
|
||||||
|
text: this.$t('chat.multichat.password.cancelled', { room })
|
||||||
|
});
|
||||||
},
|
},
|
||||||
tryConfirmRoomCreateSuccess() {
|
tryConfirmRoomCreateSuccess() {
|
||||||
if (!this.pendingRoomCreateName) return false;
|
if (!this.pendingRoomCreateName) return false;
|
||||||
@@ -2162,6 +2195,40 @@ export default {
|
|||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.room-password-panel {
|
||||||
|
margin-top: 0.6em;
|
||||||
|
margin-bottom: 0.6em;
|
||||||
|
padding: 0.6em;
|
||||||
|
border: 1px solid #d7d7d7;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #f8f9fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-password-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-password-message {
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #444;
|
||||||
|
margin-bottom: 0.45em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-password-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.45em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-password-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0.35em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-message {
|
.chat-message {
|
||||||
margin-bottom: 0.3em;
|
margin-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,10 @@
|
|||||||
"types": {}
|
"types": {}
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
|
"title": "Passwort erforderlich",
|
||||||
|
"inputLabel": "Passwort eingeben",
|
||||||
|
"submit": "Beitreten",
|
||||||
|
"cancel": "Abbrechen",
|
||||||
"requiredPrompt": "Der Raum \"{room}\" ist passwortgeschützt. Bitte Passwort eingeben:",
|
"requiredPrompt": "Der Raum \"{room}\" ist passwortgeschützt. Bitte Passwort eingeben:",
|
||||||
"invalidPrompt": "Falsches Passwort für \"{room}\". Bitte erneut eingeben:",
|
"invalidPrompt": "Falsches Passwort für \"{room}\". Bitte erneut eingeben:",
|
||||||
"cancelled": "Beitritt zu \"{room}\" abgebrochen.",
|
"cancelled": "Beitritt zu \"{room}\" abgebrochen.",
|
||||||
|
|||||||
@@ -116,6 +116,10 @@
|
|||||||
"types": {}
|
"types": {}
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
|
"title": "Password required",
|
||||||
|
"inputLabel": "Enter password",
|
||||||
|
"submit": "Join room",
|
||||||
|
"cancel": "Cancel",
|
||||||
"requiredPrompt": "Room \"{room}\" is password-protected. Please enter password:",
|
"requiredPrompt": "Room \"{room}\" is password-protected. Please enter password:",
|
||||||
"invalidPrompt": "Wrong password for \"{room}\". Please try again:",
|
"invalidPrompt": "Wrong password for \"{room}\". Please try again:",
|
||||||
"cancelled": "Join to \"{room}\" was cancelled.",
|
"cancelled": "Join to \"{room}\" was cancelled.",
|
||||||
|
|||||||
@@ -115,6 +115,10 @@
|
|||||||
"types": {}
|
"types": {}
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
|
"title": "Contraseña requerida",
|
||||||
|
"inputLabel": "Introduce la contraseña",
|
||||||
|
"submit": "Entrar en sala",
|
||||||
|
"cancel": "Cancelar",
|
||||||
"requiredPrompt": "La sala \"{room}\" está protegida por contraseña. Introduce la contraseña:",
|
"requiredPrompt": "La sala \"{room}\" está protegida por contraseña. Introduce la contraseña:",
|
||||||
"invalidPrompt": "Contraseña incorrecta para \"{room}\". Inténtalo de nuevo:",
|
"invalidPrompt": "Contraseña incorrecta para \"{room}\". Inténtalo de nuevo:",
|
||||||
"cancelled": "Se canceló el acceso a \"{room}\".",
|
"cancelled": "Se canceló el acceso a \"{room}\".",
|
||||||
|
|||||||
Reference in New Issue
Block a user