-
-
+
+
+
+
+
+
+
+
`;
+ const syncSelection = () => {
+ card.dataset.language = pendingLanguage;
+ card.querySelectorAll('[data-language]').forEach((item) => {
+ const selected = item.dataset.language === pendingLanguage;
+ item.classList.toggle('is-selected', selected);
+ item.setAttribute('aria-checked', String(selected));
+ });
+ };
+ syncSelection();
+
card.querySelectorAll('[data-language]').forEach((button) => {
button.addEventListener('click', () => {
- const language = String(button.dataset.language || 'ru');
- saveEntryLanguage(language);
- card.querySelectorAll('[data-language]').forEach((item) => {
- const selected = item === button;
- item.classList.toggle('is-selected', selected);
- item.setAttribute('aria-checked', String(selected));
- });
- sessionStorage.removeItem('shine-language-return-page');
- navigate(returnPage);
+ pendingLanguage = button.dataset.language === 'en' ? 'en' : 'ru';
+ syncSelection();
});
});
+ card.querySelector('[data-action="cancel"]')?.addEventListener('click', () => {
+ sessionStorage.removeItem('shine-language-return-page');
+ navigate(returnPage);
+ });
+ card.querySelector('[data-action="ok"]')?.addEventListener('click', () => {
+ saveEntryLanguage(pendingLanguage);
+ sessionStorage.removeItem('shine-language-return-page');
+ navigate(returnPage);
+ });
screen.append(card);
return screen;
diff --git a/shine-UI/js/pages/messages-list.js b/shine-UI/js/pages/messages-list.js
index 2772a3d0..299ff489 100644
--- a/shine-UI/js/pages/messages-list.js
+++ b/shine-UI/js/pages/messages-list.js
@@ -227,6 +227,7 @@ export function render({ navigate, chrome }) {
const chatFilterMenu = createDropdownMenu({
anchorEl: filterTitle,
align: 'left',
+ leftShift: 72,
minWidth: 225,
items: [
{ label: 'Все чаты', action: () => { currentChatFilter = 'all'; filterTitle.textContent = filterLabels.all; reloadForFilter(); } },
@@ -259,11 +260,13 @@ export function render({ navigate, chrome }) {
const menuWidth = menuPortal.offsetWidth || 206;
const left = Math.max(margin, Math.min(window.innerWidth - menuWidth - margin, rect.right - menuWidth));
menuPortal.style.left = `${Math.round(left)}px`;
- menuPortal.style.top = `${Math.round(rect.bottom + 7)}px`;
+ const titleRect = filterTitle?.getBoundingClientRect?.();
+ menuPortal.style.top = `${Math.round((titleRect?.bottom || rect.bottom) + 7)}px`;
};
const openHeadMenu = () => {
if (!menuButton || menuPortal) return;
+ document.dispatchEvent(new CustomEvent('shine:dropdown-open', { detail: { owner: menuButton } }));
const portal = document.createElement('div');
portal.className = 'dm-head-menu dm-head-menu--portal';
portal.setAttribute('role', 'menu');
@@ -304,6 +307,10 @@ export function render({ navigate, chrome }) {
if (menuPortal.contains(event.target) || menuButton?.contains(event.target)) return;
closeHeadMenu();
};
+ const onPeerDropdownOpen = (event) => {
+ if (!menuPortal || event?.detail?.owner === menuButton) return;
+ closeHeadMenu();
+ };
const onMenuKeydown = (event) => {
if (event.key !== 'Escape' || !menuPortal) return;
closeHeadMenu();
@@ -312,6 +319,7 @@ export function render({ navigate, chrome }) {
const onMenuViewportChange = () => positionHeadMenu();
document.addEventListener('click', onOutsideClick);
document.addEventListener('keydown', onMenuKeydown);
+ document.addEventListener('shine:dropdown-open', onPeerDropdownOpen);
window.addEventListener('resize', onMenuViewportChange, { passive: true });
window.addEventListener('scroll', onMenuViewportChange, { passive: true, capture: true });
@@ -487,6 +495,7 @@ function renderRow(item) {
chatFilterMenu.destroy();
document.removeEventListener('click', onOutsideClick);
document.removeEventListener('keydown', onMenuKeydown);
+ document.removeEventListener('shine:dropdown-open', onPeerDropdownOpen);
window.removeEventListener('resize', onMenuViewportChange);
window.removeEventListener('scroll', onMenuViewportChange, true);
};
diff --git a/shine-UI/styles/components.css b/shine-UI/styles/components.css
index c276cc55..3be47e4d 100644
--- a/shine-UI/styles/components.css
+++ b/shine-UI/styles/components.css
@@ -10040,10 +10040,11 @@ body.chat-topbar-overlay .composer-slot {
}
.profile-head-menu .shared-dropdown-menu__item > img {
- width: 23px;
- height: 23px;
- min-width: 23px;
- flex-basis: 23px;
+ width: 27px;
+ height: 27px;
+ min-width: 27px;
+ flex-basis: 27px;
+ filter: drop-shadow(0 0 6px rgba(101, 183, 255, 0.36));
}
.dm-head-filter-title,
@@ -10235,20 +10236,20 @@ body.chat-topbar-overlay .composer-slot {
.channels-screen--list .channel-row {
position: relative;
- width: calc(100% - 8px);
- grid-template-columns: 58px minmax(0, 1fr);
- gap: 10px;
- min-height: 64px;
- margin: 2px 4px;
- padding: 5px 8px 5px 5px;
+ width: calc(100% - 2px);
+ grid-template-columns: 46px minmax(0, 1fr);
+ gap: 8px;
+ min-height: 44px;
+ margin: 1px 1px;
+ padding: 3px 6px 3px 3px;
border-radius: 14px;
}
.channels-screen--list .channel-row .avatar {
- width: 52px;
- height: 52px;
- min-width: 52px;
- min-height: 52px;
+ width: 42px;
+ height: 42px;
+ min-width: 42px;
+ min-height: 42px;
}
.channels-screen--list .channel-row-main {
@@ -10314,3 +10315,173 @@ body.chat-topbar-overlay .composer-slot {
linear-gradient(180deg, rgba(255,255,255,.075), transparent 30%),
rgba(10, 24, 52, .68) !important;
}
+
+
+/* ===== UX refinements 2026-08-29 ===== */
+/* Start: larger breathing room between brand and actions. */
+.auth-screen--welcome .auth-brand {
+ margin-bottom: clamp(34px, 6vh, 58px) !important;
+}
+.auth-screen--welcome .shine-actions {
+ margin-top: 0;
+}
+
+/* Language selector: actual two-position switch with explicit confirmation. */
+.language-segmented-control {
+ position: relative;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 0;
+ padding: 4px;
+ min-height: 58px;
+ border: 1px solid rgba(190, 210, 238, .18);
+ border-radius: 18px;
+ background: rgba(12, 22, 40, .72);
+ overflow: hidden;
+}
+.language-segmented-thumb {
+ position: absolute;
+ z-index: 0;
+ top: 4px;
+ bottom: 4px;
+ left: 4px;
+ width: calc(50% - 4px);
+ border: 1px solid rgba(99, 190, 255, .52);
+ border-radius: 14px;
+ background: linear-gradient(180deg, rgba(76, 166, 255, .28), rgba(30, 105, 204, .20));
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 0 18px rgba(63,160,255,.14);
+ transition: transform 180ms ease;
+}
+.language-choice-card[data-language="en"] .language-segmented-thumb { transform: translateX(100%); }
+.language-segment {
+ position: relative;
+ z-index: 1;
+ min-height: 50px;
+ padding: 0 12px;
+ border: 0 !important;
+ background: transparent !important;
+ color: rgba(231,239,255,.64);
+ font-size: 16px;
+ font-weight: 650;
+}
+.language-segment.is-selected { color: #eef8ff; }
+.language-choice-actions {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 10px;
+ margin-top: 8px;
+}
+.language-choice-actions .shine-btn { height: 50px; }
+
+/* Entry settings actions use the existing Start button visual language without huge width side effects. */
+.screen-content.preauth-flow .server-check-btn.shine-btn {
+ width: auto;
+ height: 44px;
+ min-height: 44px;
+ padding-inline: 18px;
+ border-radius: 14px;
+ font-size: 15px;
+}
+.screen-content.preauth-flow .auth-footer-actions .shine-btn {
+ width: 100%;
+}
+
+/* Channels: much wider, substantially shorter rows. */
+.channels-screen--list .channels-list-content,
+.channels-screen--list .channels-groups,
+.channels-screen--list .stack:has(> .channel-row) {
+ width: calc(100% + 16px) !important;
+ margin-left: -8px !important;
+ margin-right: -8px !important;
+}
+.channels-screen--list .channel-row {
+ width: 100% !important;
+ min-height: 54px !important;
+ margin: 1px 0 !important;
+ padding: 5px 6px 5px 4px !important;
+ grid-template-columns: 50px minmax(0, 1fr) !important;
+ gap: 8px !important;
+ border-radius: 15px !important;
+}
+.channels-screen--list .channel-row .avatar {
+ width: 48px !important;
+ height: 48px !important;
+ min-width: 48px !important;
+ min-height: 48px !important;
+}
+.channels-screen--list .channel-row-main {
+ gap: 0 !important;
+ padding-right: 3px !important;
+ align-self: center;
+ overflow: hidden;
+}
+.channels-screen--list .channel-row-title,
+.channels-screen--list .channel-row-technical,
+.channels-screen--list .channel-row-description,
+.channels-screen--list .channel-row-owner {
+ margin-block: 0 !important;
+ line-height: 1.12 !important;
+}
+.channels-screen--list .channel-row-preview-line {
+ display: flex !important;
+ align-items: baseline !important;
+ gap: 7px !important;
+ min-width: 0 !important;
+ width: 100% !important;
+ line-height: 1.15 !important;
+}
+.channels-screen--list .channel-row-preview-line .channel-row-message {
+ flex: 1 1 auto !important;
+ min-width: 0 !important;
+ max-width: 100% !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ white-space: nowrap !important;
+ line-height: 1.15 !important;
+}
+.channels-screen--list .channel-row-preview-line .channel-row-time {
+ flex: 0 0 auto !important;
+ position: static !important;
+ align-self: baseline !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ line-height: 1.15 !important;
+ transform: none !important;
+ white-space: nowrap !important;
+}
+.channels-screen--list .channel-row-controls { top: 3px !important; right: 5px !important; }
+
+/* Toolbar: reserve enough vertical room for the Connections label and safe area. */
+:root { --toolbar-height: 88px; }
+.toolbar-slot {
+ min-height: calc(88px + env(safe-area-inset-bottom)) !important;
+ overflow: visible !important;
+ padding-bottom: env(safe-area-inset-bottom) !important;
+}
+.toolbar {
+ min-height: 82px !important;
+ overflow: visible !important;
+ padding-bottom: 6px !important;
+ align-items: end;
+}
+.toolbar-btn-network {
+ min-height: 72px !important;
+ align-content: end !important;
+ overflow: visible !important;
+ padding-bottom: 2px !important;
+}
+.toolbar-btn-network .toolbar-icon-img {
+ transform: translateY(-4px) !important;
+}
+.toolbar-btn-network > span:last-child {
+ display: block !important;
+ transform: translateY(-2px) !important;
+ line-height: 1.05 !important;
+ padding-bottom: 1px !important;
+}
+
+.channels-screen--list .channel-row-technical,
+.channels-screen--list .channel-row-description,
+.channels-screen--list .channel-row-owner {
+ display: none !important;
+}