[Phase50] PlanViewerWindow·SettingsWindow 분리 — 6개 파일
변경 파일: - PlanViewerWindow.StepRenderer.cs: 616 → 425줄 (RenderSteps/SwapSteps/EditStep 유지) - PlanViewerWindow.EditButtons.cs (신규): BuildApprovalButtons, BuildExecutionButtons, BuildCloseButton, ShowEditInput, CreateMiniButton, CreateActionButton (197줄) - SettingsWindow.AgentConfig.cs: 608 → 303줄 (모델/스킬/템플릿 관리 유지) - SettingsWindow.AiToggle.cs (신규): ApplyAiEnabledState, AiEnabled_Changed, NetworkMode_Changed, StepApprovalCheckBox_Checked, BtnClearMemory_Click (316줄) - SettingsWindow.AgentHooks.cs: 605 → 334줄 (훅 관리 유지) - SettingsWindow.McpAdvanced.cs (신규): MCP 서버 관리, 감사 로그, 폴백 모델, LoadAdvancedSettings/SaveAdvancedSettings (271줄) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
316
src/AxCopilot/Views/SettingsWindow.AiToggle.cs
Normal file
316
src/AxCopilot/Views/SettingsWindow.AiToggle.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using AxCopilot.Services;
|
||||
using AxCopilot.ViewModels;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
public partial class SettingsWindow
|
||||
{
|
||||
// ─── AI 기능 활성화 토글 + 네트워크 모드 ────────────────────────────────────
|
||||
|
||||
/// <summary>AI 기능 토글 상태를 UI와 설정에 반영합니다.</summary>
|
||||
private void ApplyAiEnabledState(bool enabled, bool init = false)
|
||||
{
|
||||
// 토글 스위치 체크 상태 동기화 (init 시에는 이벤트 억제)
|
||||
if (AiEnabledToggle != null && AiEnabledToggle.IsChecked != enabled)
|
||||
{
|
||||
AiEnabledToggle.IsChecked = enabled;
|
||||
}
|
||||
// AX Agent 탭 가시성
|
||||
if (AgentTabItem != null)
|
||||
AgentTabItem.Visibility = enabled ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void AiEnabled_Changed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!IsLoaded) return;
|
||||
var tryEnable = AiEnabledToggle?.IsChecked == true;
|
||||
|
||||
// 비활성화는 즉시 적용 (비밀번호 불필요)
|
||||
if (!tryEnable)
|
||||
{
|
||||
var app2 = CurrentApp;
|
||||
if (app2?.SettingsService?.Settings != null)
|
||||
{
|
||||
app2.SettingsService.Settings.AiEnabled = false;
|
||||
app2.SettingsService.Save();
|
||||
}
|
||||
ApplyAiEnabledState(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 이미 활성화된 상태에서 설정 창이 열릴 때 토글 복원으로 인한 이벤트 → 비밀번호 불필요
|
||||
var currentApp = CurrentApp;
|
||||
if (currentApp?.SettingsService?.Settings.AiEnabled == true) return;
|
||||
|
||||
// 새로 활성화하는 경우에만 비밀번호 확인
|
||||
var bgBrush = TryFindResource("LauncherBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x1E, 0x1E, 0x2E));
|
||||
var fgBrush = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||
var subFgBrush = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||
var borderBrush = TryFindResource("BorderColor") as Brush ?? new SolidColorBrush(Color.FromRgb(0x40, 0x40, 0x60));
|
||||
var itemBg = TryFindResource("ItemBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2A, 0x40));
|
||||
|
||||
var dlg = new Window
|
||||
{
|
||||
Title = "AI 기능 활성화 — 비밀번호 확인",
|
||||
Width = 340, SizeToContent = SizeToContent.Height,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
Owner = this, ResizeMode = ResizeMode.NoResize,
|
||||
WindowStyle = WindowStyle.None, AllowsTransparency = true,
|
||||
Background = Brushes.Transparent,
|
||||
};
|
||||
var border = new Border
|
||||
{
|
||||
Background = bgBrush, CornerRadius = new CornerRadius(12),
|
||||
BorderBrush = borderBrush, BorderThickness = new Thickness(1), Padding = new Thickness(20),
|
||||
};
|
||||
var stack = new StackPanel();
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "\U0001f512 AI 기능 활성화",
|
||||
FontSize = 15, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = fgBrush, Margin = new Thickness(0, 0, 0, 12),
|
||||
});
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "비밀번호를 입력하세요:",
|
||||
FontSize = 12, Foreground = subFgBrush, Margin = new Thickness(0, 0, 0, 6),
|
||||
});
|
||||
var pwBox = new PasswordBox
|
||||
{
|
||||
FontSize = 14, Padding = new Thickness(8, 6, 8, 6),
|
||||
Background = itemBg, Foreground = fgBrush, BorderBrush = borderBrush, PasswordChar = '*',
|
||||
};
|
||||
stack.Children.Add(pwBox);
|
||||
|
||||
var btnRow = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(0, 16, 0, 0) };
|
||||
var cancelBtn = new Button { Content = "취소", Padding = new Thickness(16, 6, 16, 6), Margin = new Thickness(0, 0, 8, 0) };
|
||||
cancelBtn.Click += (_, _) => { dlg.DialogResult = false; };
|
||||
btnRow.Children.Add(cancelBtn);
|
||||
var okBtn = new Button { Content = "확인", Padding = new Thickness(16, 6, 16, 6), IsDefault = true };
|
||||
okBtn.Click += (_, _) =>
|
||||
{
|
||||
if (pwBox.Password == SettingsPassword)
|
||||
dlg.DialogResult = true;
|
||||
else
|
||||
{
|
||||
pwBox.Clear();
|
||||
pwBox.Focus();
|
||||
}
|
||||
};
|
||||
btnRow.Children.Add(okBtn);
|
||||
stack.Children.Add(btnRow);
|
||||
border.Child = stack;
|
||||
dlg.Content = border;
|
||||
dlg.Loaded += (_, _) => pwBox.Focus();
|
||||
|
||||
if (dlg.ShowDialog() == true)
|
||||
{
|
||||
var app = CurrentApp;
|
||||
if (app?.SettingsService?.Settings != null)
|
||||
{
|
||||
app.SettingsService.Settings.AiEnabled = true;
|
||||
app.SettingsService.Save();
|
||||
}
|
||||
ApplyAiEnabledState(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 취소/실패 — 토글 원상복구
|
||||
if (AiEnabledToggle != null) AiEnabledToggle.IsChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 사내/사외 모드 토글 ─────────────────────────────────────────────────────
|
||||
|
||||
private const string SettingsPassword = "axgo123!";
|
||||
|
||||
private void NetworkMode_Changed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!IsLoaded) return;
|
||||
var tryInternalMode = InternalModeToggle?.IsChecked == true; // true = 사내(차단), false = 사외(허용)
|
||||
|
||||
// 사내 모드로 전환(차단 강화)은 비밀번호 불필요
|
||||
if (tryInternalMode)
|
||||
{
|
||||
var app2 = CurrentApp;
|
||||
if (app2?.SettingsService?.Settings != null)
|
||||
{
|
||||
app2.SettingsService.Settings.InternalModeEnabled = true;
|
||||
app2.SettingsService.Save();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 이미 사외 모드인 경우 토글 복원으로 인한 이벤트 → 비밀번호 불필요
|
||||
var currentApp = CurrentApp;
|
||||
if (currentApp?.SettingsService?.Settings.InternalModeEnabled == false) return;
|
||||
|
||||
// 사외 모드 활성화(외부 허용)는 비밀번호 확인 필요
|
||||
var bgBrush = TryFindResource("LauncherBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x1E, 0x1E, 0x2E));
|
||||
var fgBrush = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||
var subFgBrush = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||
var borderBrush = TryFindResource("BorderColor") as Brush ?? new SolidColorBrush(Color.FromRgb(0x40, 0x40, 0x60));
|
||||
var itemBg = TryFindResource("ItemBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2A, 0x40));
|
||||
|
||||
var dlg = new Window
|
||||
{
|
||||
Title = "사외 모드 활성화 — 비밀번호 확인",
|
||||
Width = 340, SizeToContent = SizeToContent.Height,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
Owner = this, ResizeMode = ResizeMode.NoResize,
|
||||
WindowStyle = WindowStyle.None, AllowsTransparency = true,
|
||||
Background = Brushes.Transparent,
|
||||
};
|
||||
var border = new Border
|
||||
{
|
||||
Background = bgBrush, CornerRadius = new CornerRadius(12),
|
||||
BorderBrush = borderBrush, BorderThickness = new Thickness(1), Padding = new Thickness(20),
|
||||
};
|
||||
var stack = new StackPanel();
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "🌐 사외 모드 활성화",
|
||||
FontSize = 15, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = fgBrush, Margin = new Thickness(0, 0, 0, 8),
|
||||
});
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "사외 모드에서는 인터넷 검색과 외부 HTTP 접속이 허용됩니다.\n비밀번호를 입력하세요:",
|
||||
FontSize = 12, Foreground = subFgBrush, Margin = new Thickness(0, 0, 0, 10),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
});
|
||||
var pwBox = new PasswordBox
|
||||
{
|
||||
FontSize = 14, Padding = new Thickness(8, 6, 8, 6),
|
||||
Background = itemBg, Foreground = fgBrush, BorderBrush = borderBrush, PasswordChar = '*',
|
||||
};
|
||||
stack.Children.Add(pwBox);
|
||||
|
||||
var btnRow = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(0, 16, 0, 0) };
|
||||
var cancelBtn = new Button { Content = "취소", Padding = new Thickness(16, 6, 16, 6), Margin = new Thickness(0, 0, 8, 0) };
|
||||
cancelBtn.Click += (_, _) => { dlg.DialogResult = false; };
|
||||
btnRow.Children.Add(cancelBtn);
|
||||
var okBtn = new Button { Content = "확인", Padding = new Thickness(16, 6, 16, 6), IsDefault = true };
|
||||
okBtn.Click += (_, _) =>
|
||||
{
|
||||
if (pwBox.Password == SettingsPassword)
|
||||
dlg.DialogResult = true;
|
||||
else
|
||||
{
|
||||
pwBox.Clear();
|
||||
pwBox.Focus();
|
||||
}
|
||||
};
|
||||
btnRow.Children.Add(okBtn);
|
||||
stack.Children.Add(btnRow);
|
||||
border.Child = stack;
|
||||
dlg.Content = border;
|
||||
dlg.Loaded += (_, _) => pwBox.Focus();
|
||||
|
||||
if (dlg.ShowDialog() == true)
|
||||
{
|
||||
var app = CurrentApp;
|
||||
if (app?.SettingsService?.Settings != null)
|
||||
{
|
||||
app.SettingsService.Settings.InternalModeEnabled = false;
|
||||
app.SettingsService.Save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 취소/실패 — 토글 원상복구 (사내 모드 유지)
|
||||
if (InternalModeToggle != null) InternalModeToggle.IsChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void StepApprovalCheckBox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not CheckBox cb || !cb.IsChecked.GetValueOrDefault()) return;
|
||||
// 설정 창 로드 중 바인딩에 의한 자동 Checked 이벤트 무시 (이미 활성화된 상태 복원)
|
||||
if (!IsLoaded) return;
|
||||
|
||||
// 테마 리소스 조회
|
||||
var bgBrush = TryFindResource("LauncherBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x1E, 0x1E, 0x2E));
|
||||
var fgBrush = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||
var subFgBrush = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||
var borderBrush = TryFindResource("BorderColor") as Brush ?? new SolidColorBrush(Color.FromRgb(0x40, 0x40, 0x60));
|
||||
var itemBg = TryFindResource("ItemBackground") as Brush ?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2A, 0x40));
|
||||
|
||||
var dlg = new Window
|
||||
{
|
||||
Title = "스텝 바이 스텝 승인 — 비밀번호 확인",
|
||||
Width = 340, SizeToContent = SizeToContent.Height,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
Owner = this, ResizeMode = ResizeMode.NoResize,
|
||||
WindowStyle = WindowStyle.None, AllowsTransparency = true,
|
||||
Background = Brushes.Transparent,
|
||||
};
|
||||
var border = new Border
|
||||
{
|
||||
Background = bgBrush, CornerRadius = new CornerRadius(12),
|
||||
BorderBrush = borderBrush, BorderThickness = new Thickness(1), Padding = new Thickness(20),
|
||||
};
|
||||
var stack = new StackPanel();
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "\U0001f50d 스텝 바이 스텝 승인 활성화",
|
||||
FontSize = 15, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = fgBrush, Margin = new Thickness(0, 0, 0, 12),
|
||||
});
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "개발자 비밀번호를 입력하세요:",
|
||||
FontSize = 12, Foreground = subFgBrush, Margin = new Thickness(0, 0, 0, 6),
|
||||
});
|
||||
var pwBox = new PasswordBox
|
||||
{
|
||||
FontSize = 14, Padding = new Thickness(8, 6, 8, 6),
|
||||
Background = itemBg, Foreground = fgBrush, BorderBrush = borderBrush, PasswordChar = '*',
|
||||
};
|
||||
stack.Children.Add(pwBox);
|
||||
|
||||
var btnRow = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(0, 16, 0, 0) };
|
||||
var cancelBtn = new Button { Content = "취소", Padding = new Thickness(16, 6, 16, 6), Margin = new Thickness(0, 0, 8, 0) };
|
||||
cancelBtn.Click += (_, _) => { dlg.DialogResult = false; };
|
||||
btnRow.Children.Add(cancelBtn);
|
||||
var okBtn = new Button { Content = "확인", Padding = new Thickness(16, 6, 16, 6), IsDefault = true };
|
||||
okBtn.Click += (_, _) =>
|
||||
{
|
||||
if (pwBox.Password == "mouse12#")
|
||||
dlg.DialogResult = true;
|
||||
else
|
||||
{
|
||||
pwBox.Clear();
|
||||
pwBox.Focus();
|
||||
}
|
||||
};
|
||||
btnRow.Children.Add(okBtn);
|
||||
stack.Children.Add(btnRow);
|
||||
border.Child = stack;
|
||||
dlg.Content = border;
|
||||
dlg.Loaded += (_, _) => pwBox.Focus();
|
||||
|
||||
if (dlg.ShowDialog() != true)
|
||||
{
|
||||
cb.IsChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnClearMemory_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var result = CustomMessageBox.Show(
|
||||
"에이전트 메모리를 초기화하면 학습된 모든 규칙과 선호도가 삭제됩니다.\n계속하시겠습니까?",
|
||||
"에이전트 메모리 초기화",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
if (result != MessageBoxResult.Yes) return;
|
||||
|
||||
var app = CurrentApp;
|
||||
app?.MemoryService?.Clear();
|
||||
CustomMessageBox.Show("에이전트 메모리가 초기화되었습니다.", "완료", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user