merge: 메인 갱신 중 toast 안내를 main에 반영

This commit is contained in:
2026-08-17 15:50:43 +00:00
3 changed files with 36 additions and 12 deletions
+24 -2
View File
@@ -2224,16 +2224,24 @@ test('mobile bottom controls share Ref pressed geometry while their color bases
await expect await expect
.poll(() => page.locator(manualRefreshSelector).evaluate((element) => getComputedStyle(element).boxShadow)) .poll(() => page.locator(manualRefreshSelector).evaluate((element) => getComputedStyle(element).boxShadow))
.not.toBe('none'); .not.toBe('none');
const callsBeforeManualRefresh = state.generalMeCalls;
await page.locator(manualRefreshSelector).click(); await page.locator(manualRefreshSelector).click();
await expect(page.locator(manualRefreshSelector)).toBeDisabled(); await expect(page.locator(manualRefreshSelector)).toBeEnabled();
await expect(page.locator(manualRefreshSelector)).toHaveAttribute('aria-busy', 'true');
await page.locator(manualRefreshSelector).click();
await expect(page.getByTestId('game-toast')).toContainText('이미 정보를 갱신하고 있습니다.');
await page.mouse.move(1, 1);
expect(await buttonStyle(manualRefreshSelector)).toMatchObject({ expect(await buttonStyle(manualRefreshSelector)).toMatchObject({
backgroundColor: 'rgb(33, 37, 41)', backgroundColor: 'rgb(33, 37, 41)',
borderBottomWidth: '4px', borderBottomWidth: '4px',
marginTop: '0px', marginTop: '0px',
height: 45, height: 45,
}); });
await expect(page.locator(manualRefreshSelector)).toHaveCSS('opacity', '0.55'); await expect(page.locator(manualRefreshSelector)).toHaveCSS('opacity', '1');
await page.screenshot({ path: testInfo.outputPath('mobile-refresh-busy-toast.png'), fullPage: true });
await expect(page.locator(manualRefreshSelector)).toHaveAttribute('aria-busy', 'false');
await expect(page.locator(manualRefreshSelector)).toBeEnabled(); await expect(page.locator(manualRefreshSelector)).toBeEnabled();
expect(state.generalMeCalls).toBe(callsBeforeManualRefresh + 1);
await persistArtifact(page, `${basePath.slice(1)}-mobile-bottom-ref-buttons`); await persistArtifact(page, `${basePath.slice(1)}-mobile-bottom-ref-buttons`);
}); });
@@ -2802,6 +2810,7 @@ test('realtime read-model events skip clock-only work, merge bursts, patch in pl
const operationsBeforeChangedBurst = state.operations.length; const operationsBeforeChangedBurst = state.operations.length;
state.generalName = '부드럽게갱신된장수'; state.generalName = '부드럽게갱신된장수';
state.refreshDelayMs = 1_000;
await page.evaluate(() => { await page.evaluate(() => {
const emit = (window as unknown as { __emitMainRealtime: (type: string, payload: unknown) => void }) const emit = (window as unknown as { __emitMainRealtime: (type: string, payload: unknown) => void })
.__emitMainRealtime; .__emitMainRealtime;
@@ -2823,7 +2832,20 @@ test('realtime read-model events skip clock-only work, merge bursts, patch in pl
} }
}); });
const manualRefresh = page.getByRole('button', { name: '갱 신' });
await expect(manualRefresh).toHaveAttribute('aria-busy', 'true');
await expect(manualRefresh).toBeEnabled();
await manualRefresh.click();
await expect(page.getByTestId('game-toast')).toContainText('이미 정보를 갱신하고 있습니다.');
if (autoRefreshArtifactRoot) {
await page.screenshot({
path: resolve(autoRefreshArtifactRoot, 'auto-refresh-busy-feedback.png'),
fullPage: true,
});
}
await expect.poll(() => state.generalMeCalls, { timeout: 3_000 }).toBe(callsBeforeRefresh + 1); await expect.poll(() => state.generalMeCalls, { timeout: 3_000 }).toBe(callsBeforeRefresh + 1);
state.refreshDelayMs = 300;
await expect(page.locator('[data-main-target="general"] .skeleton-line')).toHaveCount(0); await expect(page.locator('[data-main-target="general"] .skeleton-line')).toHaveCount(0);
await expect(page.locator('[data-main-target="city"] .skeleton-line')).toHaveCount(0); await expect(page.locator('[data-main-target="city"] .skeleton-line')).toHaveCount(0);
await expect(page.getByRole('button', { name: '갱 신' })).toHaveAttribute('aria-busy', 'false'); await expect(page.getByRole('button', { name: '갱 신' })).toHaveAttribute('aria-busy', 'false');
@@ -226,7 +226,6 @@ const onQuick = (item: QuickNavigationItem) => {
data-bottom-menu="manual-refresh" data-bottom-menu="manual-refresh"
aria-label="직접 갱신" aria-label="직접 갱신"
title="직접 갱신" title="직접 갱신"
:disabled="refreshing"
:aria-busy="refreshing" :aria-busy="refreshing"
@click="emit('refresh')" @click="emit('refresh')"
> >
@@ -306,12 +305,6 @@ const onQuick = (item: QuickNavigationItem) => {
line-height: 1; line-height: 1;
} }
.manual-refresh-trigger:disabled {
cursor: wait;
filter: grayscale(0.6);
opacity: 0.55;
}
.bottom-trigger.legacy-button:not(:disabled, [aria-disabled='true']):hover, .bottom-trigger.legacy-button:not(:disabled, [aria-disabled='true']):hover,
.bottom-trigger.legacy-button:not(:disabled, [aria-disabled='true'])[aria-expanded='true'] { .bottom-trigger.legacy-button:not(:disabled, [aria-disabled='true'])[aria-expanded='true'] {
height: 44px; height: 44px;
+12 -3
View File
@@ -20,11 +20,13 @@ import type { QuickNavigationItem } from '../components/main/mainNavigation';
import { formatLog } from '../utils/formatLog'; import { formatLog } from '../utils/formatLog';
import { useSessionStore } from '../stores/session'; import { useSessionStore } from '../stores/session';
import { useMainDashboardStore } from '../stores/mainDashboard'; import { useMainDashboardStore } from '../stores/mainDashboard';
import { useGameFeedback } from '../composables/useGameFeedback';
import { trpc } from '../utils/trpc'; import { trpc } from '../utils/trpc';
import type { CommandPatternEntry } from '../components/command/types'; import type { CommandPatternEntry } from '../components/command/types';
const session = useSessionStore(); const session = useSessionStore();
const dashboard = useMainDashboardStore(); const dashboard = useMainDashboardStore();
const { info: showInfoToast } = useGameFeedback();
const isMobile = useMediaQuery('(max-width: 939.98px)'); const isMobile = useMediaQuery('(max-width: 939.98px)');
const npcMode = ref(0); const npcMode = ref(0);
@@ -115,6 +117,14 @@ const loadMainData = async () => {
npcMode.value = worldState?.config.npcMode ?? 0; npcMode.value = worldState?.config.npcMode ?? 0;
}; };
const requestManualRefresh = () => {
if (refreshing.value) {
showInfoToast('이미 정보를 갱신하고 있습니다.');
return;
}
void loadMainData();
};
const moveLobby = () => { const moveLobby = () => {
window.location.replace(import.meta.env.VITE_GATEWAY_WEB_URL?.trim() || '/gateway/'); window.location.replace(import.meta.env.VITE_GATEWAY_WEB_URL?.trim() || '/gateway/');
}; };
@@ -154,9 +164,8 @@ watch(
<button <button
class="game-shell__action legacy-button legacy-button--navigation" class="game-shell__action legacy-button legacy-button--navigation"
type="button" type="button"
:disabled="refreshing"
:aria-busy="refreshing" :aria-busy="refreshing"
@click="loadMainData" @click="requestManualRefresh"
> >
</button> </button>
@@ -451,7 +460,7 @@ watch(
:npc-mode="npcMode" :npc-mode="npcMode"
:realtime-enabled="realtimeEnabled" :realtime-enabled="realtimeEnabled"
:refreshing="refreshing" :refreshing="refreshing"
@refresh="loadMainData" @refresh="requestManualRefresh"
@toggle-realtime="dashboard.setRealtimeEnabled(!realtimeEnabled)" @toggle-realtime="dashboard.setRealtimeEnabled(!realtimeEnabled)"
@lobby="moveLobby" @lobby="moveLobby"
@quick="moveQuick" @quick="moveQuick"