mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
Шапка на телефоне: одна строка — вкладки, масштаб и шестерёнка с меню остального (#616)
На окне не шире 480 px шапка карточки и страницы бокового меню занимает одну строку ≤ 56 px: вкладки пространств (без шестерёнок и «+», прокрутка вбок, текущая вкладка докручивается в видимую область), масштаб, одна шестерёнка «Действия и настройки» и у админа слот крестика #647. Заголовок скрыт. Меню шестерёнки (src/header-menu.ts): редакторы, настройки и добавление пространства, общие настройки, PDF, помощь, сводная панель и объёмный вид (alpha) — в фиксированном порядке и с теми же условиями и действиями, что у прежних кнопок. Пункт закрывает меню; Escape возвращает фокус на шестерёнку; касание вне меню поглощается прозрачной подложкой. На > 480 px шапка прежняя, в киоске меню нет. - три кнопки шапки вынесены в renderHeaderActions — шапка карточки не растёт; - сводная панель отдаёт свои пункты методом menuItems(); - i18n: title.header_menu (en/ru/de/fr); - потолок initial View 291 000 → 292 600 (замер 291 635), база bundleBytes; - смок smoke_mobile_view_header, юнит header-menu, 10 мутантов; смоки support_feedback, gear_tabs, modes, toolbar_stable_width переведены на меню на ≤ 480 px; подпись вкладки в span.tabtitle без pointer-events; - USER-GUIDE.ru, UX-MODES, TOUCH-SUPPORT, STYLING-HOOKS, data-hp-contract, оба changelog. Issue: #616 User-Visible: yes
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
// #616: состав меню шестерёнки телефонной шапки — ТЗ п.4. Порядок фиксирован,
|
||||
// условия те же, что у прежних кнопок: редакторы и настройки — только с правом
|
||||
// записи, «Добавить пространство» — без фиксированного пространства, сводная
|
||||
// панель и объёмный вид — только в просмотре, в киоске меню нет.
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { headerMenuItems } from '../test-build/header-menu.js';
|
||||
|
||||
const calls = [];
|
||||
const actions = {
|
||||
setMode: (m) => calls.push(`mode:${m}`), configureSpace: () => calls.push('configure'),
|
||||
addSpace: () => calls.push('add'), settings: () => calls.push('settings'), pdf: () => calls.push('pdf'),
|
||||
support: () => calls.push('support'), projection: (p) => calls.push(`projection:${p}`),
|
||||
};
|
||||
const summary = [{ id: 'summary-settings', label: 's', run: () => calls.push('summary-settings') },
|
||||
{ id: 'summary-toggle', label: 't', pressed: false, run: () => calls.push('summary-toggle') }];
|
||||
const input = (over = {}) => ({
|
||||
canEdit: true, kiosk: false, mode: 'view', hasFixedFloor: false, labsIso: false, iso: false,
|
||||
summary, t: (key) => `«${key}»`, actions, ...over,
|
||||
});
|
||||
const ids = (over) => headerMenuItems(input(over)).map((item) => item.id);
|
||||
const ADMIN = ['mode-plan', 'mode-devices', 'mode-decor', 'space-settings', 'space-add', 'settings', 'pdf', 'support'];
|
||||
|
||||
test('#616 админ в просмотре: редакторы · пространство · приложение · сводная панель — в этом порядке', () => {
|
||||
assert.deepEqual(ids(), [...ADMIN, 'summary-settings', 'summary-toggle']);
|
||||
});
|
||||
|
||||
test('#616 не-админ: только сводная панель; без неё меню пусто — кнопки нет', () => {
|
||||
assert.deepEqual(ids({ canEdit: false }), ['summary-settings', 'summary-toggle']);
|
||||
assert.deepEqual(ids({ canEdit: false, summary: [] }), []);
|
||||
});
|
||||
|
||||
test('#616 редактор: сводной панели и объёмного вида нет, текущий редактор отмечен', () => {
|
||||
const items = headerMenuItems(input({ mode: 'devices', labsIso: true }));
|
||||
assert.deepEqual(items.map((i) => i.id), ADMIN);
|
||||
assert.deepEqual(items.filter((i) => i.current).map((i) => i.id), ['mode-devices']);
|
||||
});
|
||||
|
||||
test('#616 фиксированное пространство убирает «Добавить пространство», киоск — всё меню', () => {
|
||||
assert.ok(!ids({ hasFixedFloor: true }).includes('space-add'));
|
||||
assert.ok(ids({ hasFixedFloor: true }).includes('space-settings'));
|
||||
assert.deepEqual(ids({ kiosk: true }), []);
|
||||
assert.deepEqual(ids({ kiosk: true, canEdit: false }), []);
|
||||
});
|
||||
|
||||
test('#616 объёмный вид — только с hp_alpha и в просмотре; пункт — переключатель', () => {
|
||||
assert.ok(!ids().includes('projection'));
|
||||
const flat = headerMenuItems(input({ labsIso: true })).at(-1);
|
||||
assert.deepEqual([flat.id, flat.pressed, flat.label], ['projection', false, '«view.volumetric»']);
|
||||
const iso = headerMenuItems(input({ labsIso: true, iso: true, canEdit: false })).at(-1);
|
||||
assert.deepEqual([iso.id, iso.pressed, iso.label], ['projection', true, '«view.flat»']);
|
||||
});
|
||||
|
||||
test('#616 каждый пункт вызывает то же действие, что прежняя кнопка', () => {
|
||||
calls.length = 0;
|
||||
for (const item of headerMenuItems(input({ labsIso: true }))) item.run();
|
||||
assert.deepEqual(calls, ['mode:plan', 'mode:devices', 'mode:decor', 'configure', 'add', 'settings', 'pdf', 'support',
|
||||
'summary-settings', 'summary-toggle', 'projection:iso']);
|
||||
});
|
||||
|
||||
test('#616 подписи — существующие ключи интерфейса', () => {
|
||||
assert.deepEqual(headerMenuItems(input({ summary: [] })).map((i) => i.label), [
|
||||
'«mode.plan»', '«mode.devices»', '«mode.decor»', '«title.configure_space»', '«title.add_space»',
|
||||
'«title.general_settings»', '«title.export_pdf»', '«support.title»',
|
||||
]);
|
||||
});
|
||||
@@ -123,7 +123,13 @@ test('Help is lazy, ordered after settings, and owns the single About/Guide surf
|
||||
assert.equal((runtime.match(/_t\('gs\.about_version'/g) || []).length, 1);
|
||||
assert.match(runtime, /docs\/USER-GUIDE\.ru\.md/);
|
||||
assert.match(runtime, /docs\/USER-GUIDE\.md/);
|
||||
assert.equal((header.match(/header-action/g) || []).length, 3);
|
||||
// #616: the three header buttons are rendered by src/header-menu.ts (the card
|
||||
// passes the openers in the same order); on a phone they are its menu items.
|
||||
const headerMenu = readFileSync(new URL('../src/header-menu.ts', import.meta.url), 'utf8');
|
||||
const actions = headerMenu.slice(headerMenu.indexOf('export function renderHeaderActions'));
|
||||
assert.equal((actions.match(/header-action/g) || []).length, 3);
|
||||
assert.ok(actions.indexOf('open.settings') < actions.indexOf('open.pdf'));
|
||||
assert.ok(actions.indexOf('open.pdf') < actions.indexOf('open.support'));
|
||||
assert.match(styles, /\.header-action\s*\{[\s\S]*?min-width:\s*44px;[\s\S]*?min-height:\s*44px;/);
|
||||
assert.match(dialogStyles, /\.supportmessage\s*\{[\s\S]*?background:\s*var\(--hp-bg\);/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user