fix(game-ui): 메인과 지도 화면 모드 경계를 통일한다

This commit is contained in:
2026-08-27 10:24:44 +00:00
parent e6824d6032
commit a35dcc78b3
5 changed files with 77 additions and 2 deletions
@@ -3083,6 +3083,51 @@ test('main cards and command input stay inside their Ref-sized grid slots', asyn
await captureProgress('mobile-500');
});
test('main layout and map use the same mobile/desktop boundary', async ({ page }, testInfo) => {
const state: NavigationFixture = {
officerLevel: 5,
permission: 2,
nationLevel: 3,
stage: 6,
npcMode: 1,
scenarioTitle: '모바일 검증 시나리오',
lastExecuted: null,
latestVote: null,
generalMeCalls: 0,
operations: [],
validMapImages: true,
};
await installFixture(page, state);
await page.setViewportSize({ width: 1000, height: 900 });
await waitForMain(page);
await expect(page.locator('.layout-desktop [data-main-target="map"] .map-area')).toBeVisible();
expect(
await page
.locator('.layout-desktop [data-main-target="map"] .map-area')
.evaluate((element) => element.getBoundingClientRect().width)
).toBe(700);
await page.screenshot({ path: testInfo.outputPath('screen-mode-desktop-1000.png'), fullPage: true });
await page.setViewportSize({ width: 940, height: 900 });
await expect(page.locator('.layout-desktop')).toBeVisible();
await expect(page.locator('.layout-desktop [data-main-target="map"] .map-area')).toBeVisible();
expect(
await page
.locator('.layout-desktop [data-main-target="map"] .map-area')
.evaluate((element) => element.getBoundingClientRect().width)
).toBeGreaterThan(500);
await page.setViewportSize({ width: 939, height: 900 });
await expect(page.locator('.layout-mobile')).toBeVisible();
await expect(page.locator('.layout-mobile [data-main-target="map"] .map-area')).toBeVisible();
expect(
await page
.locator('.layout-mobile [data-main-target="map"] .map-area')
.evaluate((element) => element.getBoundingClientRect().width)
).toBe(500);
await page.screenshot({ path: testInfo.outputPath('screen-mode-mobile-939.png'), fullPage: true });
});
test('the 939/940 boundary switches to the Ref-style 500px single document', async ({ page }) => {
const state: NavigationFixture = {
officerLevel: 5,
@@ -3630,12 +3675,20 @@ test('automatic screen mode switches wide mobile screens to the 1000px layout at
npcMode: 1,
generalMeCalls: 0,
operations: [],
validMapImages: true,
};
await installFixture(mobilePage, state);
await waitForMain(mobilePage);
const expectedWideLayout = deviceWidth >= 700;
await expect(mobilePage.locator(expectedWideLayout ? '.layout-desktop' : '.layout-mobile')).toBeVisible();
const activeMap = mobilePage.locator(
`${expectedWideLayout ? '.layout-desktop' : '.layout-mobile'} [data-main-target="map"] .map-area`
);
await expect(activeMap).toBeVisible();
expect(await activeMap.evaluate((element) => element.getBoundingClientRect().width)).toBe(
expectedWideLayout ? 700 : 500
);
expect(
await mobilePage.evaluate(() => document.querySelector<HTMLMetaElement>('meta[name="viewport"]')?.content)
).toBe(expectedWideLayout ? 'width=1000' : 'width=device-width, initial-scale=1');
@@ -3664,6 +3717,10 @@ test('automatic screen mode switches wide mobile screens to the 1000px layout at
document.dispatchEvent(new CustomEvent('tryChangeScreenMode'));
});
await expect(mobilePage.locator('.layout-mobile')).toBeVisible();
await expect(mobilePage.locator('.layout-mobile [data-main-target="map"] .map-area')).toHaveCSS(
'width',
'500px'
);
expect(
await mobilePage.evaluate(
() => document.querySelector<HTMLMetaElement>('meta[name="viewport"]')?.content
@@ -3686,6 +3743,10 @@ test('automatic screen mode switches wide mobile screens to the 1000px layout at
document.dispatchEvent(new CustomEvent('tryChangeScreenMode'));
});
await expect(mobilePage.locator('.layout-desktop')).toBeVisible();
await expect(mobilePage.locator('.layout-desktop [data-main-target="map"] .map-area')).toHaveCSS(
'width',
'700px'
);
expect(
await mobilePage.evaluate(
() => document.querySelector<HTMLMetaElement>('meta[name="viewport"]')?.content
@@ -9,6 +9,7 @@ import { useMapViewerStore } from '../../stores/mapViewer';
import { buildAssetUrl } from '../../utils/mapAssets';
import { resolveMapBackgroundPath, resolveMapSeason, resolveNextMapSeason } from '../../utils/mapBackground';
import { configuredGameAssetUrl } from '../../utils/imageAssets';
import { SCREEN_MODE_DESKTOP_MEDIA_QUERY } from '../../utils/screenModeViewport';
interface MapSummary {
year: number;
@@ -133,7 +134,7 @@ const preloadDecodedImage = (url: string): Promise<void> => {
return pending;
};
const isWide = useMediaQuery('(min-width: 1024px)');
const isWide = useMediaQuery(SCREEN_MODE_DESKTOP_MEDIA_QUERY);
const mapStore = useMapViewerStore();
const {
showCityName,
@@ -1,5 +1,8 @@
export const SCREEN_MODE_KEY = 'sam.screenMode';
export const SCREEN_MODE_CHANGE_EVENT = 'tryChangeScreenMode';
export const SCREEN_MODE_DESKTOP_MIN_WIDTH = 940;
export const SCREEN_MODE_DESKTOP_MEDIA_QUERY = `(min-width: ${SCREEN_MODE_DESKTOP_MIN_WIDTH}px)`;
export const SCREEN_MODE_MOBILE_MEDIA_QUERY = `(max-width: ${SCREEN_MODE_DESKTOP_MIN_WIDTH - 0.02}px)`;
export type ScreenMode = 'auto' | '500px' | '1000px';
+2 -1
View File
@@ -37,11 +37,12 @@ import {
MOBILE_MAIN_PANEL_ORDER_STORAGE_KEY,
type MobileMainPanelId,
} from '../utils/mobileMainPanelOrder';
import { SCREEN_MODE_MOBILE_MEDIA_QUERY } from '../utils/screenModeViewport';
const session = useSessionStore();
const dashboard = useMainDashboardStore();
const { info: showInfoToast } = useGameFeedback();
const isMobile = useMediaQuery('(max-width: 939.98px)');
const isMobile = useMediaQuery(SCREEN_MODE_MOBILE_MEDIA_QUERY);
const npcMode = ref(0);
const globalNavigation = ref<MainNavigationEntry[]>(defaultGlobalNavigation);
@@ -5,8 +5,17 @@ import {
normalizeScreenMode,
resolveAutoViewportContent,
resolveViewportContent,
SCREEN_MODE_DESKTOP_MEDIA_QUERY,
SCREEN_MODE_DESKTOP_MIN_WIDTH,
SCREEN_MODE_MOBILE_MEDIA_QUERY,
} from '../src/utils/screenModeViewport.ts';
void test('main and map layouts share one 939/940 screen-mode boundary', () => {
assert.equal(SCREEN_MODE_DESKTOP_MIN_WIDTH, 940);
assert.equal(SCREEN_MODE_DESKTOP_MEDIA_QUERY, '(min-width: 940px)');
assert.equal(SCREEN_MODE_MOBILE_MEDIA_QUERY, '(max-width: 939.98px)');
});
void test('automatic mode follows the Ref physical-screen thresholds', () => {
assert.equal(resolveAutoViewportContent({ deviceWidth: 390, viewportHeight: 844 }), 'width=500');
assert.equal(