SHA256
UI: новый общий стиль, тёмная/светлая тема, настраиваемая палитра
- styles/main.css: роли цветов (по умолчанию «Индиго»), шкала отступов/скруглений/шрифтов, цвета отношений для обеих тем; жёсткие цвета в стилях заменены на роли. - Палитра: пресеты и личные правки, «Оформление» Авто/День/Ночь, долгое нажатие — редактор цветов с экспортом/импортом. - Каналы: пузыри постов автора, плашки дней, строка «Написать в канал…», «О канале», создание канала с адресом из названия; лента открывается на свежих постах. - Чаты: плоский список, чипы-фильтры, пузыри, плашки дней; нижняя панель скрыта в переписке. - Корневые разделы — единая шапка; профиль и чужой профиль — общая карточка; настройки, кошелёк, сеансы — меню-списки. - Нижняя панель: иконки без подписей, бейджи на иконках. - confirmDialog вместо window.confirm/alert; на телефоне диалоги — шторки снизу. - docs/UI-Design/ISSUES-for-dev.md — найденные ошибки сервера/UI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@ import {
|
||||
stopAllTwemojiAnimations,
|
||||
} from '../components/emoji-picker.js?v=202607152130';
|
||||
import { isTextToSpeechConfigured, speakTextBySettings } from '../services/speech-tools-service.js';
|
||||
import { showToast } from '../services/channels-ux.js';
|
||||
import { dayKey, formatClockTime, formatDayLabel, showToast } from '../services/channels-ux.js';
|
||||
import { buildDmFileTechBlock, buildDmReplyTechBlock, parseDmTechBlocks, sanitizeUserDmTextForSend } from '../services/dm-tech-blocks.js';
|
||||
import { isDmFileTransferEnabled } from '../services/feature-settings.js';
|
||||
import {
|
||||
@@ -44,6 +44,7 @@ import { makeProfileLinksRoute, makeProfileRoute } from '../services/shine-route
|
||||
export const pageMeta = {
|
||||
id: 'chat-view',
|
||||
title: 'Чат',
|
||||
hideToolbar: true,
|
||||
shellMode: {
|
||||
topFade: true,
|
||||
bottomFade: true,
|
||||
@@ -81,7 +82,7 @@ function chatRelationLabel(value) {
|
||||
case 'close_friend': return 'Близкий друг';
|
||||
case 'friend': return 'Друг';
|
||||
case 'contact': return 'Контакт';
|
||||
default: return 'Не в контактах';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +118,9 @@ function createChatHeaderParts(login, navigate) {
|
||||
const lastName = String(currentPeer?.lastName || '').trim();
|
||||
const fullName = [firstName, lastName].filter(Boolean).join(' ');
|
||||
nameEl.textContent = fullName || cleanLogin;
|
||||
metaEl.textContent = `${cleanLogin} · ${chatRelationLabel(currentPeer?.relationType)}`;
|
||||
const relation = chatRelationLabel(currentPeer?.relationType);
|
||||
metaEl.textContent = [fullName ? `@${cleanLogin}` : '', relation].filter(Boolean).join(' · ');
|
||||
metaEl.hidden = !metaEl.textContent;
|
||||
const avatar = renderUserAvatar({
|
||||
login: cleanLogin,
|
||||
firstName,
|
||||
@@ -1058,7 +1061,19 @@ function renderLog(
|
||||
const messages = getChatMessages(chatId);
|
||||
let unreadSeparatorInserted = false;
|
||||
const separatorMessageKey = String(unreadSeparatorMessageKey || '').trim();
|
||||
let lastDayKey = '';
|
||||
messages.forEach((msg) => {
|
||||
const msgTimeMs = resolveMessageTimeMs(msg);
|
||||
const msgDayKey = dayKey(msgTimeMs);
|
||||
if (msgDayKey && msgDayKey !== lastDayKey) {
|
||||
lastDayKey = msgDayKey;
|
||||
const daySep = document.createElement('div');
|
||||
daySep.className = 'dm-day-separator';
|
||||
const dayLabel = document.createElement('span');
|
||||
dayLabel.textContent = formatDayLabel(msgTimeMs);
|
||||
daySep.append(dayLabel);
|
||||
list.append(daySep);
|
||||
}
|
||||
const isUnreadBoundary = showUnreadSeparator
|
||||
&& !unreadSeparatorInserted
|
||||
&& separatorMessageKey
|
||||
@@ -1176,7 +1191,8 @@ function renderLog(
|
||||
|
||||
const timeNode = document.createElement('span');
|
||||
timeNode.className = 'bubble-time';
|
||||
timeNode.textContent = formatMessageTime(resolveMessageTimeMs(msg));
|
||||
timeNode.textContent = formatClockTime(resolveMessageTimeMs(msg));
|
||||
timeNode.title = formatMessageTime(resolveMessageTimeMs(msg));
|
||||
metaNode.append(timeNode);
|
||||
|
||||
const status = resolveDeliveryStatus(messages, msg);
|
||||
@@ -1812,7 +1828,7 @@ export function render({ navigate, route, chrome }) {
|
||||
updateSendButtonMode();
|
||||
const denied = error?.name === 'NotAllowedError' || error?.name === 'SecurityError';
|
||||
showToast(
|
||||
denied ? 'Нужно разрешить SHiNE доступ к микрофону.' : (error?.message || 'Не удалось начать запись'),
|
||||
denied ? 'Нужно разрешить Сиянию доступ к микрофону.' : (error?.message || 'Не удалось начать запись'),
|
||||
{ kind: 'error', timeoutMs: 2600 },
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user