순정 MessageBox 를 앱 테마 대화상자로 교체 (53곳 중 49곳)
다크 테마에서 흰 시스템 창이 튀어나오던 알림을 자체 창(MessageDialogView)으로 바꿨다. 앱 셸과 같은 커스텀 타이틀바(36px) + B.Surface 본문 + 성격 아이콘 + 우측 버튼 줄. 폭 440 고정, 내용에 따라 높이 자동, 긴 예외는 스크롤로 흡수한다. 진입점은 DialogService 정적 메서드 4개로 모았다 — Notify / Confirm / ConfirmWithCancel / ShowError. MessageBox 는 Win32 호출이라 아무 데서나 되지만 WPF 창은 아니다. 교체로 새로 생기는 제약 셋을 DialogService 한곳에서 막는다. - 진단 모드에서는 창을 만들지 않고 기각 기본값을 즉시 돌려준다. 스모크는 무인 실행이라 모달이 하나라도 뜨면 타임아웃 없이 영원히 멈춘다 — 실제로 편집 스모크가 지나는 경로에 붙여넣기·개명 가드가 있다. 규약을 스모크 검사 3건으로 고정했다. - UI 스레드가 아니면 Dispatcher 로 넘긴다. - 소유 창은 '살아 있는 것'만 건다. 아직 안 보였거나 이미 닫힌 창을 Owner 로 주면 예외이고, 진단 렌더러가 도는 동안 MainWindow 가 닫힌 창을 가리킬 수 있다. App.xaml.cs 4곳은 다르게 처리했다. - 기동 실패(:49)·예외 폭주(:82)·복구 안내(:89) 3곳은 순정 유지. 창이 없는 시점이라 자체 창을 띄우면 종료코드가 유실되고, 이미 예외가 터진 자리에서 WPF 창을 새로 만들면 같은 핸들러로 재진입한다. 이유를 각 자리에 주석으로 남겼다. 덤으로 :89 는 e.Handled 를 알림보다 먼저 세우도록 순서를 바로잡았다 — 알림이 던지면 '복구 가능한 예외'가 하드 크래시로 바뀐다. - 알 수 없는 진단 옵션(:179)은 알림을 없앴다. 옵션 오타 하나로 무인 실행이 멈추던 자리다. 함께 고친 것 — Primary 버튼 스타일. 공유 버튼 템플릿의 호버 트리거가 TargetName 으로 채움을 회색으로 덮는데(TargetName 트리거는 TemplateBinding 을 이긴다) 글자는 흰색 그대로라, 라이트에서 마우스를 올리면 #F3F3F3 위 흰 글자 1.08:1 로 사라진다. 지금까지 Primary 사용처가 0건이라 드러난 적이 없었고 이 창이 첫 사용이다. 전용 템플릿 + 채움 호버·누름 토큰 2종 신설. 신설 토큰: B.Warning / B.Danger(라이트는 다크값을 못 쓴다 — 앰버 #E0A33A 는 흰 면 위 2.22:1 로 아이콘 기준 3:1 도 미달), B.AccentFillHover / B.AccentFillPressed. 전부 양 테마에 동시 추가. Lucide 아이콘 4종(info·circle-alert·triangle-alert·circle-help) 추가. 바꾸지 않은 것: 예외 원문. 18곳을 ShowError 로 수렴시키면 화면에서 ex.Message 가 오류코드+로그로 대체되는 동작 변경이 된다 — 요청은 시각 변경이라 문구·정보량을 그대로 뒀다. 남는 시스템 대화상자: 인쇄(PrintDialog)와 파일 열기/저장 — OS 셸 대화상자라 대상이 아니다. 진단 렌더러에 알림 5종(오류·경고·확인·저장확인·정보)을 등록해 라이트/다크 10장이 자동으로 남는다. 회귀: 테스트 124/124, 편집 스모크 실패 0, DB 왕복 1,271건 diff 0/예외 0, 종이 렌더 P062 바이트 동일. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bd0d055e0d
commit
604f8f7d1b
@@ -46,6 +46,12 @@ public partial class App : Application
|
||||
var config = Services.ConfigService.Current;
|
||||
if (!Services.SessionBootstrap.TryInitialize(launch, config.ConnectionString, config.DevUidCod, out var error))
|
||||
{
|
||||
// 순정 MessageBox 유지 — 테마 대화상자로 바꾸지 말 것.
|
||||
// (1) 이 시점엔 창이 하나도 없다. 기본 ShutdownMode 는 OnLastWindowClose 라 여기서 Window 를
|
||||
// 띄우면 그 창이 앱의 유일한 창이 되고, 닫는 순간 WPF 가 자동 종료를 시작해 바로 아래
|
||||
// Shutdown(2) 의 종료코드가 유실될 수 있다(런처가 실패를 성공으로 읽는다).
|
||||
// (2) ThemeManager.LoadSaved() 가 아직 아래(:54)라 라이트 사용자에게도 다크 창이 뜬다.
|
||||
// (3) '앱이 뜨지 못한다'를 알리는 마지막 통로다 — 알림 수단이 앱 상태에 의존하면 안 된다.
|
||||
MessageBox.Show(error, "서식생성기", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown(2);
|
||||
return;
|
||||
@@ -77,19 +83,24 @@ public partial class App : Application
|
||||
{
|
||||
recentCrashes.Dequeue();
|
||||
}
|
||||
// 아래 두 알림은 순정 MessageBox 를 유지한다 — 테마 대화상자로 바꾸지 말 것.
|
||||
// 여기는 이미 예외가 터진 자리다. WPF 창을 새로 만들면(템플릿 해석·DynamicResource·렌더)
|
||||
// 그 과정이 다시 던져 같은 핸들러로 재진입한다 — 무한 팝업을 막으려는 코드가 원인이 된다.
|
||||
// MessageBox 는 Win32 호출이라 WPF 렌더 스택에 의존하지 않는다.
|
||||
if (recentCrashes.Count >= 5)
|
||||
{
|
||||
e.Handled = true;
|
||||
MessageBox.Show("반복되는 오류로 프로그램을 종료합니다.\n로그를 확인해 주세요.\n오류 코드: " + code,
|
||||
"서식생성기", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
e.Handled = true;
|
||||
Shutdown(3);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handled 를 알림보다 먼저 세운다 — 알림이 던지면 '복구 가능한 예외'가 하드 크래시로 바뀐다
|
||||
e.Handled = true;
|
||||
MessageBox.Show(
|
||||
$"오류가 발생했지만 작업은 계속할 수 있습니다.\n저장하지 않은 내용이 있으면 먼저 저장해 주세요.\n\n오류 코드: {code}",
|
||||
"서식생성기", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>진단 플래그 분기 — 종료 코드를 반환한다(호출부가 Shutdown 처리)</summary>
|
||||
@@ -176,8 +187,11 @@ public partial class App : Application
|
||||
return Diagnostics.DialogShots.Run(args[1]);
|
||||
}
|
||||
|
||||
MessageBox.Show($"알 수 없는 진단 옵션입니다: {args[0]}", "서식생성기",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
// 진단 모드에서는 모달을 띄우지 않는다 — 스크립트 옵션 오타 하나로 무인 실행이 여기서
|
||||
// 영원히 멈춘다. WinExe 라 콘솔이 없어 stderr 는 호출자가 리다이렉트할 때만 보이므로
|
||||
// 로그를 함께 남긴다(--db-render 가 .err.txt 로 남기는 것과 같은 이유).
|
||||
Services.AppLog.Warn($"알 수 없는 진단 옵션입니다: {args[0]}");
|
||||
Console.Error.WriteLine($"알 수 없는 진단 옵션입니다: {args[0]}");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user