From fd41a53404cb28fd804e979e67a16af57f1ad165 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 4 Mar 2026 23:34:55 +0100 Subject: [PATCH] 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. --- .../src/dialogues/chat/MultiChatDialog.vue | 129 +++++++++++++----- frontend/src/i18n/locales/de/chat.json | 4 + frontend/src/i18n/locales/en/chat.json | 4 + frontend/src/i18n/locales/es/chat.json | 4 + 4 files changed, 110 insertions(+), 31 deletions(-) diff --git a/frontend/src/dialogues/chat/MultiChatDialog.vue b/frontend/src/dialogues/chat/MultiChatDialog.vue index d05a35a..d093421 100644 --- a/frontend/src/dialogues/chat/MultiChatDialog.vue +++ b/frontend/src/dialogues/chat/MultiChatDialog.vue @@ -172,6 +172,23 @@ +
+
{{ $t('chat.multichat.password.title') }}
+
+ {{ passwordPromptInvalid ? $t('chat.multichat.password.invalidPrompt', { room: passwordPromptRoom }) : $t('chat.multichat.password.requiredPrompt', { room: passwordPromptRoom }) }} +
+
+ + + +
+
@@ -322,7 +339,10 @@ export default { pendingRoomCreateAttempts: 0, pendingRoomCreateTimer: null, roomPasswords: {}, - passwordPromptActive: false, + passwordPromptVisible: false, + passwordPromptInvalid: false, + passwordPromptRoom: '', + passwordPromptValue: '', // Palette state paletteWidth: 420, paletteHeight: 220, @@ -371,6 +391,10 @@ export default { this.messages = []; this.usersInRoom = []; this.selectedTargetUser = null; + this.passwordPromptVisible = false; + this.passwordPromptInvalid = false; + this.passwordPromptRoom = ''; + this.passwordPromptValue = ''; } } }, @@ -411,38 +435,47 @@ export default { if (!roomName) return ''; return this.roomPasswords[roomName] || ''; }, - async handleRoomPasswordError(errorCode) { + handleRoomPasswordError(errorCode) { const room = this.getSelectedRoomName(); - if (!room || this.passwordPromptActive) return; - this.passwordPromptActive = true; - try { - const isInvalid = errorCode === 'room_password_invalid'; - const promptText = isInvalid - ? this.$t('chat.multichat.password.invalidPrompt', { room }) - : this.$t('chat.multichat.password.requiredPrompt', { room }); - const entered = window.prompt(promptText, ''); - if (entered === null) { - this.messages.push({ - id: Date.now(), - 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; + if (!room || this.passwordPromptVisible) return; + this.passwordPromptRoom = room; + this.passwordPromptInvalid = errorCode === 'room_password_invalid'; + this.passwordPromptValue = ''; + this.passwordPromptVisible = true; + }, + submitRoomPassword() { + const room = this.passwordPromptRoom || this.getSelectedRoomName(); + if (!room) { + this.passwordPromptVisible = false; + return; } + 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() { if (!this.pendingRoomCreateName) return false; @@ -2162,6 +2195,40 @@ export default { 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 { margin-bottom: 0.3em; } diff --git a/frontend/src/i18n/locales/de/chat.json b/frontend/src/i18n/locales/de/chat.json index 4bc53b9..013e47e 100644 --- a/frontend/src/i18n/locales/de/chat.json +++ b/frontend/src/i18n/locales/de/chat.json @@ -116,6 +116,10 @@ "types": {} }, "password": { + "title": "Passwort erforderlich", + "inputLabel": "Passwort eingeben", + "submit": "Beitreten", + "cancel": "Abbrechen", "requiredPrompt": "Der Raum \"{room}\" ist passwortgeschützt. Bitte Passwort eingeben:", "invalidPrompt": "Falsches Passwort für \"{room}\". Bitte erneut eingeben:", "cancelled": "Beitritt zu \"{room}\" abgebrochen.", diff --git a/frontend/src/i18n/locales/en/chat.json b/frontend/src/i18n/locales/en/chat.json index c4a5522..e142d93 100644 --- a/frontend/src/i18n/locales/en/chat.json +++ b/frontend/src/i18n/locales/en/chat.json @@ -116,6 +116,10 @@ "types": {} }, "password": { + "title": "Password required", + "inputLabel": "Enter password", + "submit": "Join room", + "cancel": "Cancel", "requiredPrompt": "Room \"{room}\" is password-protected. Please enter password:", "invalidPrompt": "Wrong password for \"{room}\". Please try again:", "cancelled": "Join to \"{room}\" was cancelled.", diff --git a/frontend/src/i18n/locales/es/chat.json b/frontend/src/i18n/locales/es/chat.json index b91ada0..dc3af8b 100644 --- a/frontend/src/i18n/locales/es/chat.json +++ b/frontend/src/i18n/locales/es/chat.json @@ -115,6 +115,10 @@ "types": {} }, "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:", "invalidPrompt": "Contraseña incorrecta para \"{room}\". Inténtalo de nuevo:", "cancelled": "Se canceló el acceso a \"{room}\".",