AX Agent 설정창 오픈 안정화: ToggleSwitch 전역 리소스화 및 테마 주입 경로 분리
Some checks failed
Release Gate / gate (push) Has been cancelled

- App.xaml: ToggleSwitch 스타일을 전역 리소스로 추가해 ChatWindow 초기화 시 StaticResource 누락 예외를 방지\n- ChatWindow.xaml.cs: Agent 설정창 오픈 시 창 전체 Resources 병합을 제거하고 AX Agent 테마 사전만 안전 주입하도록 변경\n- ChatWindow.xaml.cs: ApplyAgentThemeResources와 설정창 주입 경로에서 공통 URI 생성 로직(BuildAgentThemeDictionaryUri)으로 중복 제거\n- README.md / docs/DEVELOPMENT.md: 2026-04-04 17:12(KST) 기준 변경 이력 및 검증 결과 동기화\n- 검증: dotnet build(경고0/오류0), dotnet test 필터 59 passed
This commit is contained in:
2026-04-04 16:32:42 +09:00
parent 2e945e36d5
commit effadf7185
4 changed files with 77 additions and 10 deletions

View File

@@ -294,6 +294,7 @@ public class MyHandler : IActionHandler
| 권한 색상 체계 통일 | 권한 요약 카드/상단 배너에서 모드별 색상(Deny=녹색, Passive=파랑, Active=녹색, Plan=보라, FullAuto=주황, Silent=빨강)을 팝업 체계와 일치시킴 | | 권한 색상 체계 통일 | 권한 요약 카드/상단 배너에서 모드별 색상(Deny=녹색, Passive=파랑, Active=녹색, Plan=보라, FullAuto=주황, Silent=빨강)을 팝업 체계와 일치시킴 |
| 슬래시 네비게이션 입력 보강 | InputBox 포커스 상태에서도 방향키/Page/Home/End/Tab이 슬래시 목록 탐색에 즉시 반영되도록 키 처리 경로를 통합하고, 모든 그룹 접힘 상태에서 휠 스크롤 fallback을 추가 | | 슬래시 네비게이션 입력 보강 | InputBox 포커스 상태에서도 방향키/Page/Home/End/Tab이 슬래시 목록 탐색에 즉시 반영되도록 키 처리 경로를 통합하고, 모든 그룹 접힘 상태에서 휠 스크롤 fallback을 추가 |
| 사내/사외 모드 회귀 보강 | operationMode 전환 직후 WebSearch 동작 반영과 URL 판별 경계(HTTP/파일/mailto) 테스트를 추가해 내부 차단 정책의 즉시성/정확성을 강화 | | 사내/사외 모드 회귀 보강 | operationMode 전환 직후 WebSearch 동작 반영과 URL 판별 경계(HTTP/파일/mailto) 테스트를 추가해 내부 차단 정책의 즉시성/정확성을 강화 |
| AX Agent 설정창 오픈 안정화 | `ToggleSwitch`를 전역 리소스로 승격해 AX Agent 창 초기화 시 리소스 누락 예외를 방지하고, AX Agent 설정창에는 테마 사전만 안전 주입하도록 오픈 경로를 보강 |
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 | | Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 | | 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed | | 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |

View File

@@ -3691,3 +3691,24 @@ else:
### 3) 품질 게이트 ### 3) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0). - `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0).
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -p:UseSharedCompilation=false -nodeReuse:false --filter "FullyQualifiedName~OperationModePolicyTests|FullyQualifiedName~OperationModeReadinessTests"` 통과 (20 passed, 0 failed). - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -p:UseSharedCompilation=false -nodeReuse:false --filter "FullyQualifiedName~OperationModePolicyTests|FullyQualifiedName~OperationModeReadinessTests"` 통과 (20 passed, 0 failed).
## 2026-04-04 추가 진행 기록 (연속 실행 44차: AX Agent 설정창 오픈 안정화)
업데이트: 2026-04-04 17:12 (KST)
### 1) 전역 토글 리소스 보강
- `App.xaml`에 `ToggleSwitch` 스타일을 전역 리소스로 추가.
- 효과:
- 창별 리소스 병합 순서와 무관하게 `ToggleSwitch` 키를 항상 해석 가능.
- AX Agent 창(`ChatWindow`) 초기화 중 `StaticResource ToggleSwitch` 누락 예외 재발 방지.
### 2) AX Agent 설정창 리소스 주입 경로 개선
- `ChatWindow.OpenAgentSettingsWindow()`에서 창 전체 리소스 사전을 직접 병합하던 경로를 제거.
- 대신 AX Agent 전용 테마 사전(`Themes/AgentLight|AgentDark.xaml`)만 안전하게 주입하도록 변경.
- 효과:
- 설정창 오픈 시 리소스 충돌 위험 감소.
- 테마 일관성 유지 + 설정창 오픈 실패 가능성 완화.
### 3) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0).
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Debug --filter "ChatWindowSlashPolicyTests|OperationModePolicyTests|OperationModeReadinessTests"` 통과 (59 passed, 0 failed).

View File

@@ -19,6 +19,42 @@
<converters:WarningSubtitleColorConverter x:Key="WarningSubtitleColorConverter"/> <converters:WarningSubtitleColorConverter x:Key="WarningSubtitleColorConverter"/>
<converters:ClipboardThumbnailConverter x:Key="ClipboardThumbnailConverter"/> <converters:ClipboardThumbnailConverter x:Key="ClipboardThumbnailConverter"/>
<converters:ClipboardHasImageConverter x:Key="ClipboardHasImageConverter"/> <converters:ClipboardHasImageConverter x:Key="ClipboardHasImageConverter"/>
<!-- 전역 토글 스위치: 창별 리소스 누락 시에도 동일 스타일 보장 -->
<Style x:Key="ToggleSwitch" TargetType="CheckBox">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid Width="46" Height="26" VerticalAlignment="Center">
<Border x:Name="Track"
Width="46"
Height="26"
CornerRadius="13"
Background="#D0D0E0"/>
<Ellipse x:Name="Thumb"
Width="20"
Height="20"
Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Fill="White">
<Ellipse.Effect>
<DropShadowEffect BlurRadius="5" ShadowDepth="1" Opacity="0.25" Direction="270"/>
</Ellipse.Effect>
</Ellipse>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Track" Property="Background" Value="{DynamicResource AccentColor}"/>
<Setter TargetName="Thumb" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="Thumb" Property="Margin" Value="0,0,3,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>
</Application> </Application>

View File

@@ -803,13 +803,7 @@ public partial class ChatWindow : Window
private void ApplyAgentThemeResources() private void ApplyAgentThemeResources()
{ {
var selected = (_settings.Settings.Llm.AgentTheme ?? "system").Trim().ToLowerInvariant(); var themeUri = BuildAgentThemeDictionaryUri();
var effective = selected switch
{
"light" => "AgentLight",
"dark" => "AgentDark",
_ => IsSystemDarkTheme() ? "AgentDark" : "AgentLight",
};
try try
{ {
@@ -818,7 +812,7 @@ public partial class ChatWindow : Window
_agentThemeDictionary = new ResourceDictionary _agentThemeDictionary = new ResourceDictionary
{ {
Source = new Uri($"pack://application:,,,/Themes/{effective}.xaml"), Source = themeUri,
}; };
Resources.MergedDictionaries.Insert(0, _agentThemeDictionary); Resources.MergedDictionaries.Insert(0, _agentThemeDictionary);
} }
@@ -828,6 +822,18 @@ public partial class ChatWindow : Window
} }
} }
private Uri BuildAgentThemeDictionaryUri()
{
var selected = (_settings.Settings.Llm.AgentTheme ?? "system").Trim().ToLowerInvariant();
var effective = selected switch
{
"light" => "AgentLight",
"dark" => "AgentDark",
_ => IsSystemDarkTheme() ? "AgentDark" : "AgentLight",
};
return new Uri($"pack://application:,,,/Themes/{effective}.xaml");
}
private static bool IsSystemDarkTheme() private static bool IsSystemDarkTheme()
{ {
try try
@@ -12974,11 +12980,14 @@ public partial class ChatWindow : Window
win.Closed += (_, _) => _agentSettingsWindow = null; win.Closed += (_, _) => _agentSettingsWindow = null;
try try
{ {
win.Resources.MergedDictionaries.Add(Resources); win.Resources.MergedDictionaries.Insert(0, new ResourceDictionary
{
Source = BuildAgentThemeDictionaryUri(),
});
} }
catch catch
{ {
// 리소스 병합 실패 시에도 설정창 자체는 열리도록 유지 // 테마 사전 로드 실패 시에도 설정창 자체는 열리도록 유지
} }
bool changed; bool changed;