feat(web): вход с 2FA сразу, панель пользователя, модальные настройки, markdown

По правкам пользователя:

- вход: поле «Код 2FA или резервный код» видно сразу, принимает 14-символьные
  резервные коды (раньше влезало 6 цифр), пустое значение не ломает вход;
- нижняя панель: одна подложка, слева аватар и имя с мини-профилем и выбором
  статуса, справа микрофон, камера, наушники (переключатели, стрелка с выбором
  устройства и громкости, переход в «Аудио-видео») и шестерёнка;
- кнопка «Покинуть сервер» из сайдбара убрана (выход — в «Опасной зоне»);
- настройки открываются модальным окном со списком пунктов; «Профиль» имеет
  вкладки «Основной» и «Сервер» (список серверов, ник и «Применить ко всем
  серверам»), аватар загружается и удаляется, есть часовой пояс (МСК по
  умолчанию);
- markdown: добавлены ==выделение==, __жирный__, ***оба***, ||спойлер||, #канал;
- двойной клик по сообщению ставит ответ (не срабатывает на ссылках, кнопках и
  при выделенном тексте);
- 219 тестов Vitest (было 176), check/lint/test/build зелёные.
This commit is contained in:
2026-09-20 01:32:11 +03:00
parent f26728113d
commit 20eed227ca
31 changed files with 2731 additions and 478 deletions
+98 -9
View File
@@ -100,15 +100,16 @@
"email": "Email",
"emailPlaceholder": "you@example.com",
"password": "Password",
"totp": "2FA code",
"totpHint": "Six digits from your authenticator app.",
"totp": "2FA or recovery code",
"totpHint": "If 2FA is enabled; a recovery code like xxxx-xxxx-xxxx also works.",
"submit": "Sign in",
"submitting": "Signing in…",
"noAccount": "No account yet?",
"registerLink": "Create one",
"forgot": "Forgot your password? Ask the instance admin.",
"instanceStatus": "Instance status",
"registrationDisabled": "Registration on this instance is disabled by the admin."
"registrationDisabled": "Registration on this instance is disabled by the admin.",
"totpRequired": "Enter the 2FA or recovery code — sign-in needs it."
},
"register": {
"title": "Create account",
@@ -219,7 +220,8 @@
},
"selectUnread": "Open channel {{name}}, {{count}} unread",
"selectMentions": "Open channel {{name}}, {{count}} mentions",
"slowmode": "slowmode {{seconds}}s"
"slowmode": "slowmode {{seconds}}s",
"leaveHint": "You can leave the server in server settings → “Danger zone”."
},
"chat": {
"log": "Message log of {{name}}",
@@ -309,7 +311,11 @@
"empty": "Nothing found."
},
"unread": "Unread messages: {{count}}",
"mentions": "Mentions: {{count}}"
"mentions": "Mentions: {{count}}",
"spoiler": {
"show": "Reveal spoiler",
"hide": "Hide spoiler"
}
},
"user": {
"panelLabel": "User panel",
@@ -319,7 +325,8 @@
"open": "Open the user menu",
"account": "Account settings",
"guilds": "Server settings",
"status": "Status"
"status": "Status",
"noBio": "No bio yet."
},
"logout": "Sign out",
"loggingOut": "Signing out…",
@@ -331,6 +338,29 @@
"dnd": "Do not disturb",
"invisible": "Invisible",
"offline": "Offline"
},
"voice": {
"input": "Input device",
"output": "Output device",
"camera": "Camera",
"micVolume": "Microphone volume",
"outputVolume": "Sound volume",
"micOn": "Unmute microphone",
"micOff": "Mute microphone",
"cameraOn": "Turn camera on",
"cameraOff": "Turn camera off",
"soundOn": "Undeafen",
"soundOff": "Deafen",
"micSettings": "Microphone settings",
"cameraSettings": "Camera settings",
"soundSettings": "Sound settings",
"audioSettings": "Audio & video settings"
},
"devices": {
"default": "Default device",
"unavailable": "Devices are unavailable",
"empty": "No devices found",
"unnamed": "Device {{index}}"
}
},
"gateway": {
@@ -357,6 +387,9 @@
"profile": "Profile",
"security": "Security",
"appearance": "Appearance",
"notifications": "Notifications",
"voice": "Audio & video",
"language": "Language & region",
"instance": "Instance"
},
"profile": {
@@ -375,7 +408,31 @@
"username": "Username",
"userId": "User ID",
"badges": "Badges",
"noBadges": "none"
"noBadges": "none",
"tabsLabel": "Profile tabs",
"tabs": {
"main": "General",
"server": "Server"
},
"timezone": "Time zone",
"timezoneHint": "Used to show message times.",
"timezoneDefault": "default (MSK)",
"avatar": {
"title": "Avatar",
"hint": "Everyone can see this picture.",
"preview": "Avatar preview",
"choose": "Choose an avatar file",
"upload": "Upload avatar",
"remove": "Remove avatar",
"limit": "Up to {{limit}}; PNG, JPEG, WebP or GIF.",
"tooLarge": "The file is larger than {{limit}} — pick a smaller image."
},
"decorations": {
"title": "Decorations",
"hint": "Profile badges and frames.",
"empty": "No decorations yet.",
"stub": "Badges, frames and profile effects are coming later."
}
},
"security": {
"title": "Security",
@@ -467,7 +524,13 @@
"placeholder": "Leave empty to reset the nickname",
"current": "Current nickname:",
"none": "not set",
"saved": "Nickname saved."
"saved": "Nickname saved.",
"applyAll": "Apply to all servers",
"applyAllHint": "One nickname for every server you are in.",
"applyAllPending": "Applying…",
"applyAllProgress": "Servers updated: {{done}} of {{total}}",
"applyAllDone": "Nickname applied on all servers ({{total}}).",
"applyAllFailed": "Failed to update servers: {{failed}}."
},
"members": {
"title": "Members",
@@ -497,7 +560,33 @@
"deleteConfirmTitle": "Delete the server?",
"deleteConfirmBody": "“{{name}}” will be deleted permanently.",
"deleteConfirm": "Delete"
}
},
"selectLabel": "Choose a server"
},
"navLabel": "Settings sections",
"notifications": {
"title": "Notifications",
"description": "Sounds, mentions and web push.",
"stub": "Notification settings are coming later."
},
"voice": {
"title": "Audio & video",
"description": "Input and output devices and volume.",
"input": "Microphone",
"camera": "Camera",
"output": "Sound",
"micVolume": "Microphone volume",
"outputVolume": "Sound volume",
"stub": "Voice channels arrive in the next phase — for now these settings are only stored."
},
"language": {
"title": "Language & region",
"description": "Time zone and interface language.",
"timezone": "Time zone",
"timezoneHint": "Used for message times.",
"locale": "Interface language",
"localeHint": "Applies immediately.",
"saved": "Region settings saved."
}
}
}