diff --git a/src/shared/versions.js b/src/shared/versions.js index 723370b..164aa3a 100644 --- a/src/shared/versions.js +++ b/src/shared/versions.js @@ -1,6 +1,6 @@ export const HARBOR_VERSIONS = Object.freeze({ - macClient: '0.7.20', - gatewayClient: '0.7.20', + macClient: '0.7.21', + gatewayClient: '0.7.21', gatewayBackend: '0.7.1', }); diff --git a/src/web/components/ServerPicker.jsx b/src/web/components/ServerPicker.jsx index 2dea6e2..2a9ae55 100644 --- a/src/web/components/ServerPicker.jsx +++ b/src/web/components/ServerPicker.jsx @@ -10,6 +10,7 @@ import { const FAVORITES_KEY = 'harbor-server-favorites'; const RECENT_KEY = 'harbor-server-recent'; const AUTO_KEY = 'harbor-server-auto'; +const SIMPLE_SERVER_LIMIT = 5; function readList(key) { try { @@ -188,7 +189,7 @@ export function ServerPicker({ const simpleServers = [ ...(selected ? [selected] : []), ...servers.filter(({ id }) => id !== selectedServerId), - ].slice(0, SERVER_RESULT_WINDOW); + ].slice(0, SIMPLE_SERVER_LIMIT); return
{prompt && Выберите сервер} @@ -274,7 +275,7 @@ export function ServerPicker({ {autoActive ? serverHealthText(pings[selectedServerId]) : 'Первый стабильный сервер'} - {selected && !autoActive && assert.match(power, /grid-column:\s*2/); assert.match(form, /grid-column:\s*3/); assert.match(form, /position:\s*static/); + assert.match(form, /overflow:\s*visible/); assert.doesNotMatch(form, /\bleft\s*:|translateX|transition:[^;]*(?:left|width|transform)/); assert.match(styles, /\.client-panel\.has-subscription \.client-form \{[\s\S]*height:\s*var\(--client-work-height\)/); assert.match(rule('.client-form-content'), /align-content:\s*start/); @@ -29,6 +30,17 @@ test('desktop layout keeps the power control on a symmetric center axis', () => assert.match(styles, /\.client-panel\.has-subscription \.client-form-content \{[\s\S]*padding-top:\s*var\(--client-power-top\)/); }); +test('server rows scroll without moving the subscription column or showing a scrollbar', () => { + const scroll = rule('.client-server-scroll'); + const simpleScroll = rule('.client-server-mode-panel.is-simple .client-server-scroll'); + + assert.match(scroll, /overflow-y:\s*auto/); + assert.match(scroll, /scrollbar-width:\s*none/); + assert.match(styles, /\.client-server-scroll::-webkit-scrollbar\s*\{[\s\S]*display:\s*none/); + assert.match(simpleScroll, /max-height:\s*none/); + assert.match(simpleScroll, /overflow:\s*visible/); +}); + test('tablet and mobile regions use normal flow with viewport-safe widths', () => { const responsive = /@media \(max-width: 920px\) \{([\s\S]*?)\n\}\n\n@media \(max-width: 560px\)/.exec(styles)?.[1] || ''; diff --git a/test/web/server-picker.test.js b/test/web/server-picker.test.js index 7cc08ba..3853289 100644 --- a/test/web/server-picker.test.js +++ b/test/web/server-picker.test.js @@ -63,5 +63,7 @@ test('server picker starts simple and reveals advanced controls on demand', () = assert.match(picker, /client-server-mode-panel is-advanced/); assert.match(picker, /inert={advanced \? true : undefined}/); assert.match(picker, /inert={!advanced \? true : undefined}/); - assert.match(picker, /\.slice\(0, SERVER_RESULT_WINDOW\)/); + assert.match(picker, /const SIMPLE_SERVER_LIMIT = 5/); + assert.match(picker, /\.slice\(0, SIMPLE_SERVER_LIMIT\)/); + assert.match(picker, /\{selected &&