UI: мультиаккаунты профиля и улучшенный поиск каналов

This commit is contained in:
AidarKC
2026-05-14 16:28:17 +03:00
parent 56a69ab683
commit 94263a46bd
9 changed files with 329 additions and 30 deletions
+31 -11
View File
@@ -409,6 +409,19 @@ function normalizeChannelDescription(value) {
return text;
}
function validatePersonalChannelName(value) {
const normalized = normalizeChannelDisplayName(value);
if (!normalized) return { ok: false, error: 'Введите логин пользователя.' };
const length = Array.from(normalized).length;
if (length < 1 || length > 20) {
return { ok: false, error: 'Логин: 1-20 символов.' };
}
if (!/^[A-Za-z0-9_]+$/.test(normalized)) {
return { ok: false, error: 'Логин: разрешены только латиница, цифры и _.' };
}
return { ok: true, normalized };
}
function makeCreateChannelBodyBytes({
lineCode,
prevLineNumber,
@@ -419,9 +432,14 @@ function makeCreateChannelBodyBytes({
channelType = CHANNEL_TYPE_PUBLIC,
channelTypeVersion = CHANNEL_TYPE_VERSION_DEFAULT,
}) {
const check = validateChannelDisplayName(channelName);
if (!check.ok) throw new Error(channelNameErrorText(check.code));
const cleanName = check.normalized;
const typeCode = Number(channelType);
const nameCheck = typeCode === CHANNEL_TYPE_PERSONAL
? validatePersonalChannelName(channelName)
: validateChannelDisplayName(channelName);
if (!nameCheck.ok) {
throw new Error(typeCode === CHANNEL_TYPE_PERSONAL ? nameCheck.error : channelNameErrorText(nameCheck.code));
}
const cleanName = nameCheck.normalized;
const cleanDescription = normalizeChannelDescription(channelDescription);
const nameBytes = utf8Bytes(cleanName);
@@ -433,7 +451,6 @@ function makeCreateChannelBodyBytes({
if (descriptionBytes.length > 200) {
throw new Error('Описание канала слишком длинное: максимум 200 символов.');
}
const typeCode = Number(channelType);
const typeVer = Number(channelTypeVersion);
if (!Number.isFinite(typeCode) || typeCode < 0 || typeCode > 65535) {
throw new Error('Некорректный тип канала.');
@@ -463,8 +480,8 @@ function makeCreateChannelBodyBytesLegacy({
thisLineNumber,
channelName,
}) {
const check = validateChannelDisplayName(channelName);
if (!check.ok) throw new Error(channelNameErrorText(check.code));
const check = validatePersonalChannelName(channelName);
if (!check.ok) throw new Error(check.error);
const cleanName = check.normalized;
const nameBytes = utf8Bytes(cleanName);
if (nameBytes.length < 1 || nameBytes.length > 255) {
@@ -1063,13 +1080,16 @@ export class AuthService {
const cleanLogin = (login || '').trim();
if (!cleanLogin) throw new Error('Missing login');
const check = validateChannelDisplayName(channelName);
if (!check.ok) throw new Error(channelNameErrorText(check.code));
const cleanChannelName = normalizeChannelDisplayName(check.normalized);
const typeCode = Number(channelType);
const nameCheck = typeCode === CHANNEL_TYPE_PERSONAL
? validatePersonalChannelName(channelName)
: validateChannelDisplayName(channelName);
if (!nameCheck.ok) {
throw new Error(typeCode === CHANNEL_TYPE_PERSONAL ? nameCheck.error : channelNameErrorText(nameCheck.code));
}
const cleanChannelName = normalizeChannelDisplayName(nameCheck.normalized);
const cleanChannelDescription = normalizeChannelDescription(channelDescription);
const channelSlug = toCanonicalChannelSlug(cleanChannelName);
const typeCode = Number(channelType);
const typeVersion = Number(channelTypeVersion);
const key = `create-channel:${cleanLogin}:${typeCode}:${channelSlug || cleanChannelName.toLowerCase()}`;
return this.runWriteLocked(key, async () => {