작업 폴더 선택 팝업을 검색과 요약 스트립 중심 구조에서 최근 폴더 목록 중심 구조로 재구성했다. 현재 선택 체크가 보이는 최근 폴더 목록과 다른 폴더 선택 액션만 남겨 캡처와 비슷한 빠른 선택 흐름으로 정리했다. README와 DEVELOPMENT 문서에 변경 이력과 시점을 반영했다. 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0 / 오류 0)
This commit is contained in:
@@ -1023,3 +1023,5 @@ MIT License
|
|||||||
- AX Agent 빈 상태 상단 심볼은 더 크게 키우고, 대화 주제/작업 유형 프리셋 카드 내부 아이콘은 한 단계 줄여 시각 균형을 조정했다.
|
- AX Agent 빈 상태 상단 심볼은 더 크게 키우고, 대화 주제/작업 유형 프리셋 카드 내부 아이콘은 한 단계 줄여 시각 균형을 조정했다.
|
||||||
- 업데이트: 2026-04-05 19:46 (KST)
|
- 업데이트: 2026-04-05 19:46 (KST)
|
||||||
- 모델 빠른 설정 팝업에서 하단 중복 모델 칩 줄을 제거하고, 하단 모델 라벨은 서비스+모델 조합 대신 현재 모델명만 보이도록 더 심플하게 정리했다.
|
- 모델 빠른 설정 팝업에서 하단 중복 모델 칩 줄을 제거하고, 하단 모델 라벨은 서비스+모델 조합 대신 현재 모델명만 보이도록 더 심플하게 정리했다.
|
||||||
|
- 업데이트: 2026-04-05 19:53 (KST)
|
||||||
|
- 작업 폴더 선택 팝업을 검색/요약 중심 구조에서 `최근 폴더 목록 + 현재 선택 체크 + 다른 폴더 선택` 형태로 단순화해 더 빠르게 고를 수 있게 정리했다.
|
||||||
|
|||||||
@@ -4768,3 +4768,5 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
|||||||
- `ChatWindow` 빈 상태 상단 심볼 크기를 확대하고, 프리셋 카드/기타/프리셋 추가 카드의 내부 아이콘 크기를 축소해 화면 비율을 정리했다.
|
- `ChatWindow` 빈 상태 상단 심볼 크기를 확대하고, 프리셋 카드/기타/프리셋 추가 카드의 내부 아이콘 크기를 축소해 화면 비율을 정리했다.
|
||||||
- 업데이트: 2026-04-05 19:46 (KST)
|
- 업데이트: 2026-04-05 19:46 (KST)
|
||||||
- `ChatWindow` 모델 선택 팝업의 중복 `InlineModelChipPanel`을 제거하고, 하단 `ModelLabel`은 현재 모델명 중심으로 단순화해 Claude류의 간결한 표시 방식에 가깝게 조정했다.
|
- `ChatWindow` 모델 선택 팝업의 중복 `InlineModelChipPanel`을 제거하고, 하단 `ModelLabel`은 현재 모델명 중심으로 단순화해 Claude류의 간결한 표시 방식에 가깝게 조정했다.
|
||||||
|
- 업데이트: 2026-04-05 19:53 (KST)
|
||||||
|
- `ChatWindow` 작업 폴더 팝업을 최근 목록 중심 UI로 재구성하고, 검색 박스와 요약 스트립을 제거해 `최근 폴더 + 다른 폴더 선택` 흐름으로 단순화했다.
|
||||||
|
|||||||
@@ -1502,48 +1502,23 @@
|
|||||||
AllowsTransparency="True" PopupAnimation="Fade">
|
AllowsTransparency="True" PopupAnimation="Fade">
|
||||||
<Border Background="{DynamicResource LauncherBackground}"
|
<Border Background="{DynamicResource LauncherBackground}"
|
||||||
BorderBrush="{DynamicResource BorderColor}"
|
BorderBrush="{DynamicResource BorderColor}"
|
||||||
BorderThickness="1" CornerRadius="16">
|
BorderThickness="1"
|
||||||
|
CornerRadius="16"
|
||||||
|
MinWidth="286"
|
||||||
|
MaxWidth="332">
|
||||||
<Border.Effect>
|
<Border.Effect>
|
||||||
<DropShadowEffect BlurRadius="22" ShadowDepth="0" Opacity="0.14"/>
|
<DropShadowEffect BlurRadius="22" ShadowDepth="0" Opacity="0.14"/>
|
||||||
</Border.Effect>
|
</Border.Effect>
|
||||||
<StackPanel Margin="0">
|
<StackPanel Margin="0">
|
||||||
<TextBlock Text="워크스페이스 선택"
|
<TextBlock Text="최근"
|
||||||
Margin="16,14,16,6"
|
Margin="16,14,16,10"
|
||||||
FontSize="12.5"
|
FontSize="12.5"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
<Border Margin="4,4,4,8"
|
|
||||||
CornerRadius="10"
|
|
||||||
BorderBrush="{DynamicResource BorderColor}"
|
|
||||||
BorderThickness="1"
|
|
||||||
Background="{DynamicResource ItemBackground}">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock Text=""
|
|
||||||
FontFamily="Segoe MDL2 Assets"
|
|
||||||
FontSize="11"
|
|
||||||
Foreground="{DynamicResource SecondaryText}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Margin="10,0,8,0"/>
|
|
||||||
<TextBox x:Name="FolderMenuSearchBox"
|
|
||||||
Grid.Column="1"
|
|
||||||
BorderThickness="0"
|
|
||||||
Background="Transparent"
|
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
|
||||||
CaretBrush="{DynamicResource AccentColor}"
|
|
||||||
FontSize="11.5"
|
|
||||||
Padding="0,8,10,8"
|
|
||||||
ToolTip="프로젝트 검색"
|
|
||||||
TextChanged="FolderMenuSearchBox_TextChanged"/>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
<ScrollViewer MaxHeight="360"
|
<ScrollViewer MaxHeight="360"
|
||||||
VerticalScrollBarVisibility="Auto"
|
VerticalScrollBarVisibility="Auto"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
Padding="4,0,4,8">
|
Padding="10,0,10,10">
|
||||||
<StackPanel x:Name="FolderMenuItems" Margin="2"/>
|
<StackPanel x:Name="FolderMenuItems" Margin="2"/>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ public partial class ChatWindow : Window
|
|||||||
private readonly HashSet<string> _sessionPermissionRules = new(StringComparer.OrdinalIgnoreCase);
|
private readonly HashSet<string> _sessionPermissionRules = new(StringComparer.OrdinalIgnoreCase);
|
||||||
private readonly Dictionary<string, bool> _sessionMcpEnabledOverrides = new(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, bool> _sessionMcpEnabledOverrides = new(StringComparer.OrdinalIgnoreCase);
|
||||||
private readonly Dictionary<string, string> _sessionMcpAuthTokens = new(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, string> _sessionMcpAuthTokens = new(StringComparer.OrdinalIgnoreCase);
|
||||||
private string _folderMenuSearchText = "";
|
|
||||||
|
|
||||||
// 경과 시간 표시
|
// 경과 시간 표시
|
||||||
private readonly DispatcherTimer _elapsedTimer;
|
private readonly DispatcherTimer _elapsedTimer;
|
||||||
private DateTime _streamStartTime;
|
private DateTime _streamStartTime;
|
||||||
@@ -1360,14 +1358,12 @@ public partial class ChatWindow : Window
|
|||||||
private void FolderPathLabel_Click(object sender, MouseButtonEventArgs e) => ShowFolderMenu();
|
private void FolderPathLabel_Click(object sender, MouseButtonEventArgs e) => ShowFolderMenu();
|
||||||
private void FolderMenuSearchBox_TextChanged(object sender, TextChangedEventArgs e)
|
private void FolderMenuSearchBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
{
|
{
|
||||||
_folderMenuSearchText = FolderMenuSearchBox?.Text?.Trim() ?? "";
|
RenderFolderMenuItems(null);
|
||||||
RenderFolderMenuItems(_folderMenuSearchText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowFolderMenu()
|
private void ShowFolderMenu()
|
||||||
{
|
{
|
||||||
_folderMenuSearchText = FolderMenuSearchBox?.Text?.Trim() ?? "";
|
RenderFolderMenuItems(null);
|
||||||
RenderFolderMenuItems(_folderMenuSearchText);
|
|
||||||
FolderMenuPopup.IsOpen = true;
|
FolderMenuPopup.IsOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1378,8 +1374,6 @@ public partial class ChatWindow : Window
|
|||||||
var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;
|
var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;
|
||||||
var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||||
var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
||||||
var query = (searchText ?? "").Trim();
|
|
||||||
|
|
||||||
var maxDisplay = Math.Clamp(_settings.Settings.Llm.MaxRecentFolders, 3, 30);
|
var maxDisplay = Math.Clamp(_settings.Settings.Llm.MaxRecentFolders, 3, 30);
|
||||||
var currentFolder = GetCurrentWorkFolder();
|
var currentFolder = GetCurrentWorkFolder();
|
||||||
var conversationFolders = _storage.LoadAllMeta()
|
var conversationFolders = _storage.LoadAllMeta()
|
||||||
@@ -1394,31 +1388,13 @@ public partial class ChatWindow : Window
|
|||||||
.Concat(conversationFolders)
|
.Concat(conversationFolders)
|
||||||
.Concat(string.IsNullOrWhiteSpace(currentFolder) ? Enumerable.Empty<string>() : new[] { currentFolder })
|
.Concat(string.IsNullOrWhiteSpace(currentFolder) ? Enumerable.Empty<string>() : new[] { currentFolder })
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.Where(path =>
|
.Take(maxDisplay * 2)
|
||||||
string.IsNullOrWhiteSpace(query)
|
|
||||||
|| path.Contains(query, StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| System.IO.Path.GetFileName(path).Contains(query, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.Take(maxDisplay * 3)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var filteredRecent = recentFolders
|
var filteredRecent = recentFolders
|
||||||
.Where(path =>
|
|
||||||
string.IsNullOrWhiteSpace(query)
|
|
||||||
|| path.Contains(query, StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| System.IO.Path.GetFileName(path).Contains(query, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.Take(maxDisplay)
|
.Take(maxDisplay)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var currentWorkspaceName = string.IsNullOrWhiteSpace(currentFolder)
|
|
||||||
? "없음"
|
|
||||||
: System.IO.Path.GetFileName(currentFolder.TrimEnd('\\', '/'));
|
|
||||||
FolderMenuItems.Children.Add(CreatePopupSummaryStrip(new[]
|
|
||||||
{
|
|
||||||
("현재", currentWorkspaceName, "#F8FAFC", "#E2E8F0", "#475569"),
|
|
||||||
("최근", filteredRecent.Count.ToString(), "#EFF6FF", "#BFDBFE", "#1D4ED8"),
|
|
||||||
("전체", workspaceFolders.Count.ToString(), "#F5F3FF", "#DDD6FE", "#6D28D9"),
|
|
||||||
}));
|
|
||||||
|
|
||||||
void AddWorkspaceRows(IEnumerable<string> folders)
|
void AddWorkspaceRows(IEnumerable<string> folders)
|
||||||
{
|
{
|
||||||
foreach (var folder in folders)
|
foreach (var folder in folders)
|
||||||
@@ -1426,9 +1402,9 @@ public partial class ChatWindow : Window
|
|||||||
var isActive = folder.Equals(currentFolder, StringComparison.OrdinalIgnoreCase);
|
var isActive = folder.Equals(currentFolder, StringComparison.OrdinalIgnoreCase);
|
||||||
var displayName = System.IO.Path.GetFileName(folder);
|
var displayName = System.IO.Path.GetFileName(folder);
|
||||||
if (string.IsNullOrEmpty(displayName)) displayName = folder;
|
if (string.IsNullOrEmpty(displayName)) displayName = folder;
|
||||||
var detailText = isActive ? $"현재 선택 · {folder}" : folder;
|
var detailText = folder;
|
||||||
var itemBorder = CreatePopupMenuRow(
|
var itemBorder = CreatePopupMenuRow(
|
||||||
isActive ? "\uE73E" : "\uE8B7",
|
"\uE8B7",
|
||||||
displayName,
|
displayName,
|
||||||
detailText,
|
detailText,
|
||||||
isActive,
|
isActive,
|
||||||
@@ -1454,7 +1430,6 @@ public partial class ChatWindow : Window
|
|||||||
|
|
||||||
if (filteredRecent.Count > 0)
|
if (filteredRecent.Count > 0)
|
||||||
{
|
{
|
||||||
FolderMenuItems.Children.Add(CreatePopupSectionLabel($"최근 워크스페이스 · {filteredRecent.Count}", new Thickness(10, 6, 10, 4)));
|
|
||||||
AddWorkspaceRows(filteredRecent);
|
AddWorkspaceRows(filteredRecent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1464,46 +1439,51 @@ public partial class ChatWindow : Window
|
|||||||
|
|
||||||
if (remainingFolders.Count > 0)
|
if (remainingFolders.Count > 0)
|
||||||
{
|
{
|
||||||
var workspaceLabel = filteredRecent.Count > 0
|
|
||||||
? $"전체 워크스페이스 · {remainingFolders.Count}"
|
|
||||||
: $"워크스페이스 · {remainingFolders.Count}";
|
|
||||||
FolderMenuItems.Children.Add(CreatePopupSectionLabel(workspaceLabel, new Thickness(10, 6, 10, 4)));
|
|
||||||
AddWorkspaceRows(remainingFolders);
|
|
||||||
|
|
||||||
FolderMenuItems.Children.Add(new Border
|
FolderMenuItems.Children.Add(new Border
|
||||||
{
|
{
|
||||||
Height = 1,
|
Height = 1,
|
||||||
Background = TryFindResource("BorderColor") as Brush ?? Brushes.Gray,
|
Background = TryFindResource("BorderColor") as Brush ?? Brushes.Gray,
|
||||||
Margin = new Thickness(8, 4, 8, 4),
|
Margin = new Thickness(8, 4, 8, 8),
|
||||||
Opacity = 0.5,
|
Opacity = 0.45,
|
||||||
});
|
});
|
||||||
|
AddWorkspaceRows(remainingFolders);
|
||||||
}
|
}
|
||||||
else if (filteredRecent.Count == 0)
|
|
||||||
|
if (filteredRecent.Count == 0 && remainingFolders.Count == 0)
|
||||||
{
|
{
|
||||||
FolderMenuItems.Children.Add(new TextBlock
|
FolderMenuItems.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = "검색 결과가 없습니다.",
|
Text = "최근 작업 폴더가 없습니다.",
|
||||||
FontSize = 11.5,
|
FontSize = 11.5,
|
||||||
Foreground = secondaryText,
|
Foreground = secondaryText,
|
||||||
Margin = new Thickness(10, 8, 10, 10),
|
Margin = new Thickness(10, 6, 10, 10),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 폴더 찾아보기 버튼
|
FolderMenuItems.Children.Add(new Border
|
||||||
|
{
|
||||||
|
Height = 1,
|
||||||
|
Background = TryFindResource("BorderColor") as Brush ?? Brushes.Gray,
|
||||||
|
Margin = new Thickness(8, 8, 8, 8),
|
||||||
|
Opacity = 0.45,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 다른 폴더 선택 버튼
|
||||||
var browseSp = new StackPanel { Orientation = Orientation.Horizontal };
|
var browseSp = new StackPanel { Orientation = Orientation.Horizontal };
|
||||||
browseSp.Children.Add(new TextBlock
|
browseSp.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = "\uED25",
|
Text = "\uE710",
|
||||||
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
||||||
FontSize = 14,
|
FontSize = 13,
|
||||||
Foreground = accentBrush,
|
Foreground = accentBrush,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
Margin = new Thickness(0, 0, 8, 0),
|
Margin = new Thickness(0, 0, 8, 0),
|
||||||
});
|
});
|
||||||
browseSp.Children.Add(new TextBlock
|
browseSp.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = "폴더 찾아보기...",
|
Text = "다른 폴더 선택",
|
||||||
FontSize = 14,
|
FontSize = 13,
|
||||||
|
FontWeight = FontWeights.SemiBold,
|
||||||
Foreground = primaryText,
|
Foreground = primaryText,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user